Ejemplo n.º 1
0
    def sync_versions(self):
        """
        Read the remote index and playlists. Return their versions, so it can
        be decided if synchronization is required. For the index, a
        `lastModified` property is available in SubSonic's responses. A similar
        property exists for playlists since SubSonic 5.3.
        """

        state = self.state["synchronizers"][self.index]

        items_version = 0
        containers_version = 0

        # Items version (last modified property). The ifModifiedSince property
        # is in milliseconds.
        response = self.subsonic.getIndexes(
            ifModifiedSince=state["items_version"] or 0)

        if "lastModified" in response["indexes"]:
            items_version = response["indexes"]["lastModified"]
        else:
            items_version = state["items_version"]

        # Playlists
        response = self.subsonic.getPlaylists()

        for playlist in response["playlists"]["playlist"]:
            containers_checksum = utils.dict_checksum(playlist)
            containers_version = (containers_version + containers_checksum) \
                % 0xFFFFFFFF

        # Return version numbers
        self.items_version = items_version
        self.containers_version = containers_version
Ejemplo n.º 2
0
    def sync_versions(self):
        """
        Read the remote index and playlists. Return their versions, so it can
        be decided if synchronization is required. For the index, a
        `lastModified` property is available in SubSonic's responses. A similar
        property exists for playlists since SubSonic 5.3.
        """

        state = self.state["synchronizers"][self.index]

        items_version = 0
        containers_version = 0

        # Items version (last modified property). The ifModifiedSince property
        # is in milliseconds.
        response = self.subsonic.getIndexes(
            ifModifiedSince=state["items_version"] or 0)

        if "lastModified" in response["indexes"]:
            items_version = response["indexes"]["lastModified"]
        else:
            items_version = state["items_version"]

        # Playlists
        response = self.subsonic.getPlaylists()

        for playlist in response["playlists"]["playlist"]:
            containers_checksum = utils.dict_checksum(playlist)
            containers_version = (containers_version + containers_checksum) \
                % 0xFFFFFFFF

        # Return version numbers
        self.items_version = items_version
        self.containers_version = containers_version
Ejemplo n.º 3
0
    def sync_base_container(self):
        """
        """

        # Calculate checksum
        checksum = utils.dict_checksum(is_base=True,
                                       is_smart=False,
                                       name=self.name)

        # Fetch existing item
        try:
            row = self.cursor.query_one(
                """
                SELECT
                    `containers`.`id`,
                    `containers`.`checksum`
                FROM
                    `containers`
                WHERE
                    `containers`.`database_id` = ? AND
                    `containers`.`is_base` = 1
                """, self.database_id)
        except IndexError:
            row = None

        # To insert or to update
        if row is None:
            base_container_id = self.cursor.query(
                """
                INSERT INTO `containers` (
                   `persistent_id`,
                   `database_id`,
                   `name`,
                   `is_base`,
                   `is_smart`,
                   `checksum`)
                VALUES
                   (?, ?, ?, ?, ?, ?)
                """, generate_persistent_id(), self.database_id, self.name,
                True, False, checksum).lastrowid
        elif row["checksum"] != checksum:
            base_container_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `containers`
                SET
                    `name` = ?,
                    `is_base` = ?,
                    `is_smart` = ?,
                    `checksum` = ?
                WHERE
                    `containers`.`id` = ?
                """, self.name, True, False, checksum, base_container_id)
        else:
            base_container_id = row["id"]

        # Update cache
        self.base_container_id = base_container_id
Ejemplo n.º 4
0
    def sync_database(self):
        """
        """

        # Calculate checksum
        checksum = utils.dict_checksum(
            name=self.name, remote_id=self.index)

        # Fetch existing item
        try:
            row = self.cursor.query_one(
                """
                SELECT
                    `databases`.`id`,
                    `databases`.`checksum`
                FROM
                    `databases`
                WHERE
                    `databases`.`remote_id` = ?
                """, self.index)
        except IndexError:
            row = None

        # To insert or to update
        if row is None:
            database_id = self.cursor.query(
                """
                INSERT INTO `databases` (
                    `persistent_id`,
                    `name`,
                    `checksum`,
                    `remote_id`)
                VALUES
                    (?, ?, ?, ?)
                """,
                generate_persistent_id(),
                self.name,
                checksum,
                self.index).lastrowid
        elif row["checksum"] != checksum:
            database_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `databases`
                SET
                    `name` = ?,
                    `checksum` = ?
                WHERE
                    `databases`.`id` = ?
                """,
                self.name,
                checksum,
                database_id)
        else:
            database_id = row["id"]

        # Update cache
        self.database_id = database_id
Ejemplo n.º 5
0
    def sync_album(self, album):
        """
        """

        logger.debug("[Album:%s] %s", album['id'], album['name'])

        checksum = utils.dict_checksum(album)
        artist_row = self.artists_by_remote_id.get(album.get("artistId"))

        # Fetch existing item
        try:
            row = self.albums_by_remote_id[album["id"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            album_id = self.cursor.query(
                """
                INSERT INTO `albums` (
                   `database_id`,
                   `artist_id`,
                   `name`,
                   `art`,
                   `checksum`,
                   `remote_id`)
                VALUES
                   (?, ?, ?, ?, ?, ?)
                """, self.database_id,
                artist_row["id"] if artist_row else None, album["name"],
                "coverArt" in album, checksum, album["id"]).lastrowid
        elif row["checksum"] != checksum:
            album_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `albums`
                SET
                   `name` = ?,
                   `art` = ?,
                   `checksum` = ?
                WHERE
                    `albums`.`id` = ?
                """, album["name"], "coverArt" in album, checksum, album_id)
        else:
            updated = False
            album_id = row["id"]

        # Update cache
        self.albums_by_remote_id[int(album["id"])] = {
            "remote_id": album["id"],
            "id": album_id,
            "artist_id": artist_row["id"],
            "checksum": checksum,
            "updated": updated
        }
Ejemplo n.º 6
0
    def sync_artist(self, item):
        """
        """

        logger.debug("[Artist:%s] %s", item['artistId'], item['artist'])

        checksum = utils.dict_checksum(name=item["artist"])

        # Fetch existing item
        try:
            row = self.artists_by_remote_id[item["artistId"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            artist_id = self.cursor.query(
                """
                INSERT INTO `artists` (
                    `database_id`,
                    `name`,
                    `remote_id`,
                    `checksum`)
                VALUES
                    (?, ?, ?, ?)
                """,
                self.database_id,
                item["artist"],
                item["artistId"],
                checksum).lastrowid
        elif row["checksum"] != checksum:
            artist_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `artists`
                SET
                    `name` = ?,
                    `checksum` = ?
                WHERE
                    `artists`.`id` = ?
                """,
                item["artist"],
                checksum,
                artist_id)
        else:
            updated = False
            artist_id = row["id"]

        # Update cache
        self.artists_by_remote_id[item["artistId"]] = {
            "remote_id": item["artistId"],
            "id": artist_id,
            "checksum": checksum,
            "updated": updated
        }
Ejemplo n.º 7
0
    def sync_artist(self, item):
        """
        """

        logger.debug("[Artist:%s] %s", item['artistId'], item['artist'])

        checksum = utils.dict_checksum(name=item["artist"])

        # Fetch existing item
        try:
            row = self.artists_by_remote_id[item["artistId"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            artist_id = self.cursor.query(
                """
                INSERT INTO `artists` (
                    `database_id`,
                    `name`,
                    `remote_id`,
                    `checksum`)
                VALUES
                    (?, ?, ?, ?)
                """, self.database_id, item["artist"], item["artistId"],
                checksum).lastrowid
        elif row["checksum"] != checksum:
            artist_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `artists`
                SET
                    `name` = ?,
                    `checksum` = ?
                WHERE
                    `artists`.`id` = ?
                """, item["artist"], checksum, artist_id)
        else:
            updated = False
            artist_id = row["id"]

        # Update cache
        self.artists_by_remote_id[item["artistId"]] = {
            "remote_id": item["artistId"],
            "id": artist_id,
            "checksum": checksum,
            "updated": updated
        }
Ejemplo n.º 8
0
    def sync_database(self):
        """
        """

        # Calculate checksum
        checksum = utils.dict_checksum(name=self.name, remote_id=self.index)

        # Fetch existing item
        try:
            row = self.cursor.query_one(
                """
                SELECT
                    `databases`.`id`,
                    `databases`.`checksum`
                FROM
                    `databases`
                WHERE
                    `databases`.`remote_id` = ?
                """, self.index)
        except IndexError:
            row = None

        # To insert or to update
        if row is None:
            database_id = self.cursor.query(
                """
                INSERT INTO `databases` (
                    `persistent_id`,
                    `name`,
                    `checksum`,
                    `remote_id`)
                VALUES
                    (?, ?, ?, ?)
                """, generate_persistent_id(), self.name, checksum,
                self.index).lastrowid
        elif row["checksum"] != checksum:
            database_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `databases`
                SET
                    `name` = ?,
                    `checksum` = ?
                WHERE
                    `databases`.`id` = ?
                """, self.name, checksum, database_id)
        else:
            database_id = row["id"]

        # Update cache
        self.database_id = database_id
Ejemplo n.º 9
0
    def sync_container(self, container):
        """
        """

        checksum = utils.dict_checksum(is_base=False,
                                       name=container["name"],
                                       song_count=container["songCount"],
                                       changed=container["changed"])

        # Fetch existing item
        try:
            row = self.containers_by_remote_id[container["id"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            container_id = self.cursor.query(
                """
                INSERT INTO `containers` (
                   `persistent_id`,
                   `database_id`,
                   `parent_id`,
                   `name`,
                   `is_base`,
                   `is_smart`,
                   `checksum`,
                   `remote_id`)
                VALUES
                   (?, ?, ?, ?, ?, ?, ?, ?)
                """, generate_persistent_id(), self.database_id,
                self.base_container_id, container["name"], False, False,
                checksum, container["id"]).lastrowid
        elif row["checksum"] != checksum:
            container_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `containers`
                SET
                    `name` = ?,
                    `is_base` = ?,
                    `is_smart` = ?,
                    `checksum` = ?
                WHERE
                    `containers`.`id` = ?
                """, container["name"], False, False, checksum, container_id)
        else:
            updated = False
            container_id = row["id"]

        # Update cache
        self.containers_by_remote_id[container["id"]] = {
            "remote_id": container["id"],
            "id": container_id,
            "checksum": checksum,
            "updated": updated,
            "container_items": []
        }
Ejemplo n.º 10
0
    def sync_item(self, item):
        """
        """

        logger.debug("[Item:%s] %s", item['id'], item['title'])

        def find_artist_by_id(artist_id):
            for artist in self.artists_by_remote_id.itervalues():
                if artist["id"] == artist_id:
                    return artist

        checksum = utils.dict_checksum(item)

        album = self.albums_by_remote_id.get(item.get("albumId"))
        artist = self.artists_by_remote_id.get(item.get("artistId"))
        album_artist = find_artist_by_id(album["artist_id"]) if album else None

        # The artist can be none, which is the case for items with featuring
        # artists.
        if artist is None and item.get("artist"):
            artist = self.synthetic_artists_by_name.get(item["artist"])

        # If there still is no artist, use the album artist.
        if not artist and album_artist:
            artist = album_artist

        # Fetch existing item
        try:
            row = self.items_by_remote_id[item["id"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            item_id = self.cursor.query(
                """
                INSERT INTO `items` (
                    `persistent_id`,
                    `database_id`,
                    `artist_id`,
                    `album_artist_id`,
                    `album_id`,
                    `name`,
                    `genre`,
                    `year`,
                    `track`,
                    `duration`,
                    `bitrate`,
                    `file_name`,
                    `file_type`,
                    `file_suffix`,
                    `file_size`,
                    `checksum`,
                    `remote_id`)
                VALUES
                    (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                """, generate_persistent_id(), self.database_id,
                artist["id"] if artist else None,
                album_artist["id"] if album_artist else None,
                album["id"] if album else None, item.get("title"),
                item.get("genre"), item.get("year"), item.get("track"),
                item["duration"] * 1000 if "duration" in item else None,
                item.get("bitRate"), item.get("path"), item.get("contentType"),
                item.get("suffix"), item.get("size"), checksum,
                item["id"]).lastrowid
        elif row["checksum"] != checksum:
            item_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `items`
                SET
                    `artist_id` = ?,
                    `album_artist_id` = ?,
                    `album_id` = ?,
                    `name` = ?,
                    `genre` = ?,
                    `year` = ?,
                    `track` = ?,
                    `duration` = ?,
                    `bitrate` = ?,
                    `file_name` = ?,
                    `file_type` = ?,
                    `file_suffix` = ?,
                    `file_size` = ?,
                    `checksum` = ?
                WHERE
                    `items`.`id` = ?
                """, artist["id"] if artist else None,
                album_artist["id"] if album_artist else None,
                album["id"] if album else None, item.get("title"),
                item.get("genre"), item.get("year"), item.get("track"),
                item["duration"] * 1000 if "duration" in item else None,
                item.get("bitRate"), item.get("path"), item.get("contentType"),
                item.get("suffix"), item.get("size"), checksum, item_id)
        else:
            updated = False
            item_id = row["id"]

        # Update cache
        self.items_by_remote_id[item["id"]] = {
            "remote_id": item["id"],
            "id": item_id,
            "checksum": checksum,
            "updated": updated
        }
Ejemplo n.º 11
0
    def synchronize(self, initial=False):
        """
        """

        logger.info("Starting synchronization.")

        server_changed = False
        items_changed = False
        containers_changed = False

        state = self.state["synchronizers"][self.index]

        # Check connection version when initial is True. In this case, the
        # synchronization step is skipped if the connection checksum has not
        # changed and some usable data is in the database.
        connection_version = utils.dict_checksum(
            baseUrl=self.subsonic.baseUrl,
            port=self.subsonic.port,
            username=self.subsonic.username,
            password=self.subsonic.password)

        if initial:
            self.is_initial_synced = True

            if state["connection_version"] != connection_version:
                logger.info("Initial synchronization is required.")
                server_changed = True
            else:
                # The initial state should be committed, even though no
                # synchronization is required.
                self.provider.update()

                return

        # Start session
        try:
            with self.db.get_write_cursor() as cursor:
                # Prepare variables
                self.cursor = cursor

                # Determine version numbers
                logger.debug("Synchronizing version numbers.")

                self.sync_versions()

                # Start synchronizing
                logger.debug("Synchronizing database and base container.")

                self.sync_database()
                self.sync_base_container()

                self.items_by_remote_id = self.cursor.query_dict(
                    """
                    SELECT
                        `items`.`remote_id`,
                        `items`.`id`,
                        `items`.`checksum`
                    FROM
                        `items`
                    WHERE
                        `items`.`database_id` = ?
                    """, self.database_id)
                self.artists_by_remote_id = {}
                self.albums_by_remote_id = {}
                self.base_container_items_by_item_id = {}
                self.containers_by_remote_id = {}

                # Items
                logger.debug("Synchronizing items.")

                if self.items_version != state.get("items_version"):
                    self.sync_items()
                    items_changed = True
                else:
                    logger.info("Items haven't been modified.")

                # Containers
                logger.debug("Synchronizing containers.")

                if self.containers_version != state.get("containers_version"):
                    self.sync_containers()
                    containers_changed = True
                else:
                    logger.info("Containers haven't been modified.")

            # Merge changes into the server. Lock access to provider because
            # multiple synchronizers could be active.
            self.update_server(items_changed, containers_changed)
        finally:
            # Make sure that everything is cleaned up
            self.cursor = None

            self.items_by_remote_id = {}
            self.artists_by_remote_id = {}
            self.albums_by_remote_id = {}
            self.base_container_items_by_item_id = {}
            self.containers_by_remote_id = {}

        # Update state if items and/or containers have changed.
        if items_changed or containers_changed or server_changed:
            state["connection_version"] = connection_version
            state["items_version"] = self.items_version
            state["containers_version"] = self.containers_version

            self.state.save()

        logger.info("Synchronization finished.")
Ejemplo n.º 12
0
    def sync_container(self, container):
        """
        """

        checksum = utils.dict_checksum(
            is_base=False, name=container["name"],
            song_count=container["songCount"], changed=container["changed"])

        # Fetch existing item
        try:
            row = self.containers_by_remote_id[container["id"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            container_id = self.cursor.query(
                """
                INSERT INTO `containers` (
                   `persistent_id`,
                   `database_id`,
                   `parent_id`,
                   `name`,
                   `is_base`,
                   `is_smart`,
                   `checksum`,
                   `remote_id`)
                VALUES
                   (?, ?, ?, ?, ?, ?, ?, ?)
                """,
                generate_persistent_id(),
                self.database_id,
                self.base_container_id,
                container["name"],
                False,
                False,
                checksum,
                container["id"]).lastrowid
        elif row["checksum"] != checksum:
            container_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `containers`
                SET
                    `name` = ?,
                    `is_base` = ?,
                    `is_smart` = ?,
                    `checksum` = ?
                WHERE
                    `containers`.`id` = ?
                """,
                container["name"],
                False,
                False,
                checksum,
                container_id)
        else:
            updated = False
            container_id = row["id"]

        # Update cache
        self.containers_by_remote_id[container["id"]] = {
            "remote_id": container["id"],
            "id": container_id,
            "checksum": checksum,
            "updated": updated,
            "container_items": []
        }
Ejemplo n.º 13
0
    def sync_album(self, album):
        """
        """

        logger.debug("[Album:%s] %s", album['id'], album['name'])

        checksum = utils.dict_checksum(album)
        artist_row = self.artists_by_remote_id.get(album.get("artistId"))

        # Fetch existing item
        try:
            row = self.albums_by_remote_id[album["id"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            album_id = self.cursor.query(
                """
                INSERT INTO `albums` (
                   `database_id`,
                   `artist_id`,
                   `name`,
                   `art`,
                   `checksum`,
                   `remote_id`)
                VALUES
                   (?, ?, ?, ?, ?, ?)
                """,
                self.database_id,
                artist_row["id"] if artist_row else None,
                album["name"],
                "coverArt" in album,
                checksum,
                album["id"]).lastrowid
        elif row["checksum"] != checksum:
            album_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `albums`
                SET
                   `name` = ?,
                   `art` = ?,
                   `checksum` = ?
                WHERE
                    `albums`.`id` = ?
                """,
                album["name"],
                "coverArt" in album,
                checksum,
                album_id)
        else:
            updated = False
            album_id = row["id"]

        # Update cache
        self.albums_by_remote_id[int(album["id"])] = {
            "remote_id": album["id"],
            "id": album_id,
            "artist_id": artist_row["id"],
            "checksum": checksum,
            "updated": updated
        }
Ejemplo n.º 14
0
    def sync_item(self, item):
        """
        """
        
        logger.debug("[Item:%s] %s", item['id'], item['title'])

        def find_artist_by_id(artist_id):
            for artist in self.artists_by_remote_id.itervalues():
                if artist["id"] == artist_id:
                    return artist

        checksum = utils.dict_checksum(item)

        album = self.albums_by_remote_id.get(item.get("albumId"))
        artist = self.artists_by_remote_id.get(item.get("artistId"))
        album_artist = find_artist_by_id(album["artist_id"]) if album else None

        # The artist can be none, which is the case for items with featuring
        # artists.
        if artist is None and item.get("artist"):
            artist = self.synthetic_artists_by_name.get(item["artist"])

        # If there still is no artist, use the album artist.
        if not artist and album_artist:
            artist = album_artist

        # Fetch existing item
        try:
            row = self.items_by_remote_id[item["id"]]
        except KeyError:
            row = None

        # To insert or to update
        updated = True

        if row is None:
            item_id = self.cursor.query(
                """
                INSERT INTO `items` (
                    `persistent_id`,
                    `database_id`,
                    `artist_id`,
                    `album_artist_id`,
                    `album_id`,
                    `name`,
                    `genre`,
                    `year`,
                    `track`,
                    `duration`,
                    `bitrate`,
                    `file_name`,
                    `file_type`,
                    `file_suffix`,
                    `file_size`,
                    `checksum`,
                    `remote_id`)
                VALUES
                    (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                """,
                generate_persistent_id(),
                self.database_id,
                artist["id"] if artist else None,
                album_artist["id"] if album_artist else None,
                album["id"] if album else None,
                item.get("title"),
                item.get("genre"),
                item.get("year"),
                item.get("track"),
                item["duration"] * 1000 if "duration" in item else None,
                item.get("bitRate"),
                item.get("path"),
                item.get("contentType"),
                item.get("suffix"),
                item.get("size"),
                checksum,
                item["id"]).lastrowid
        elif row["checksum"] != checksum:
            item_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `items`
                SET
                    `artist_id` = ?,
                    `album_artist_id` = ?,
                    `album_id` = ?,
                    `name` = ?,
                    `genre` = ?,
                    `year` = ?,
                    `track` = ?,
                    `duration` = ?,
                    `bitrate` = ?,
                    `file_name` = ?,
                    `file_type` = ?,
                    `file_suffix` = ?,
                    `file_size` = ?,
                    `checksum` = ?
                WHERE
                    `items`.`id` = ?
                """,
                artist["id"] if artist else None,
                album_artist["id"] if album_artist else None,
                album["id"] if album else None,
                item.get("title"),
                item.get("genre"),
                item.get("year"),
                item.get("track"),
                item["duration"] * 1000 if "duration" in item else None,
                item.get("bitRate"),
                item.get("path"),
                item.get("contentType"),
                item.get("suffix"),
                item.get("size"),
                checksum,
                item_id)
        else:
            updated = False
            item_id = row["id"]

        # Update cache
        self.items_by_remote_id[item["id"]] = {
            "remote_id": item["id"],
            "id": item_id,
            "checksum": checksum,
            "updated": updated
        }
Ejemplo n.º 15
0
    def synchronize(self, initial=False):
        """
        """

        logger.info("Starting synchronization.")

        server_changed = False
        items_changed = False
        containers_changed = False

        state = self.state["synchronizers"][self.index]

        # Check connection version when initial is True. In this case, the
        # synchronization step is skipped if the connection checksum has not
        # changed and some usable data is in the database.
        connection_version = utils.dict_checksum(
            baseUrl=self.subsonic.baseUrl,
            port=self.subsonic.port,
            username=self.subsonic.username,
            password=self.subsonic.password)

        if initial:
            self.is_initial_synced = True

            if state["connection_version"] != connection_version:
                logger.info("Initial synchronization is required.")
                server_changed = True
            else:
                # The initial state should be committed, even though no
                # synchronization is required.
                self.provider.update()

                return

        # Start session
        try:
            with self.db.get_write_cursor() as cursor:
                # Prepare variables
                self.cursor = cursor

                # Determine version numbers
                logger.debug("Synchronizing version numbers.")

                self.sync_versions()

                # Start synchronizing
                logger.debug("Synchronizing database and base container.")

                self.sync_database()
                self.sync_base_container()

                self.items_by_remote_id = self.cursor.query_dict(
                    """
                    SELECT
                        `items`.`remote_id`,
                        `items`.`id`,
                        `items`.`checksum`
                    FROM
                        `items`
                    WHERE
                        `items`.`database_id` = ?
                    """, self.database_id)
                self.artists_by_remote_id = {}
                self.albums_by_remote_id = {}
                self.base_container_items_by_item_id = {}
                self.containers_by_remote_id = {}

                # Items
                logger.debug("Synchronizing items.")

                if self.items_version != state.get("items_version"):
                    self.sync_items()
                    items_changed = True
                else:
                    logger.info("Items haven't been modified.")

                # Containers
                logger.debug("Synchronizing containers.")

                if self.containers_version != state.get("containers_version"):
                    self.sync_containers()
                    containers_changed = True
                else:
                    logger.info("Containers haven't been modified.")

            # Merge changes into the server. Lock access to provider because
            # multiple synchronizers could be active.
            self.update_server(items_changed, containers_changed)
        finally:
            # Make sure that everything is cleaned up
            self.cursor = None

            self.items_by_remote_id = {}
            self.artists_by_remote_id = {}
            self.albums_by_remote_id = {}
            self.base_container_items_by_item_id = {}
            self.containers_by_remote_id = {}

        # Update state if items and/or containers have changed.
        if items_changed or containers_changed or server_changed:
            state["connection_version"] = connection_version
            state["items_version"] = self.items_version
            state["containers_version"] = self.containers_version

            self.state.save()

        logger.info("Synchronization finished.")
Ejemplo n.º 16
0
    def sync_base_container(self):
        """
        """

        # Calculate checksum
        checksum = utils.dict_checksum(
            is_base=True, is_smart=False, name=self.name)

        # Fetch existing item
        try:
            row = self.cursor.query_one(
                """
                SELECT
                    `containers`.`id`,
                    `containers`.`checksum`
                FROM
                    `containers`
                WHERE
                    `containers`.`database_id` = ? AND
                    `containers`.`is_base` = 1
                """, self.database_id)
        except IndexError:
            row = None

        # To insert or to update
        if row is None:
            base_container_id = self.cursor.query(
                """
                INSERT INTO `containers` (
                   `persistent_id`,
                   `database_id`,
                   `name`,
                   `is_base`,
                   `is_smart`,
                   `checksum`)
                VALUES
                   (?, ?, ?, ?, ?, ?)
                """,
                generate_persistent_id(),
                self.database_id,
                self.name,
                True,
                False,
                checksum).lastrowid
        elif row["checksum"] != checksum:
            base_container_id = row["id"]
            self.cursor.query(
                """
                UPDATE
                    `containers`
                SET
                    `name` = ?,
                    `is_base` = ?,
                    `is_smart` = ?,
                    `checksum` = ?
                WHERE
                    `containers`.`id` = ?
                """,
                self.name,
                True,
                False,
                checksum,
                base_container_id)
        else:
            base_container_id = row["id"]

        # Update cache
        self.base_container_id = base_container_id