[rygel] server: Cleanup and fix container updates in content directory.



commit 67767f9531db3ae1424bf260addbe9d2c03fd776
Author: Krzesimir Nowak <krnowak openismus com>
Date:   Tue Feb 26 12:52:57 2013 +0100

    server: Cleanup and fix container updates in content directory.
    
    RygelContentDirectory's on_container_update handles updating system
    update id, running service reset procedure if necessary, adding
    LastChange entries, updating container's and object's update ids and
    handles ContainerUpdateIDs variable in one body. This commit splits it
    up, so it is more readable and fixes updating container's and object's
    container/object update ids.
    
    Now container gets its container update id incremented also when its
    child item is being modified. We also check if passed object is a
    container, so we can also increment its container update id as well.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694019

 src/librygel-server/rygel-content-directory.vala |  113 ++++++++++++++++-----
 1 files changed, 86 insertions(+), 27 deletions(-)
---
diff --git a/src/librygel-server/rygel-content-directory.vala 
b/src/librygel-server/rygel-content-directory.vala
index 8f9048d..809297e 100644
--- a/src/librygel-server/rygel-content-directory.vala
+++ b/src/librygel-server/rygel-content-directory.vala
@@ -416,43 +416,64 @@ internal class Rygel.ContentDirectory: Service {
         return update_ids;
     }
 
-    /**
-     * handler for container_updated signal on root_container. We don't
-     * immediately send the notification for changes but schedule the
-     * notification after 0.2 seconds. Also we don't clear the updated
-     * container list immediately after notification but rather in this
-     * function. Please refer to ContentDirectory version 2 specs for details
-     * on why we do all this the way we do.
-     *
-     * @param root_container the root_container
-     * @param updated_container the container that just got updated
-     */
-    private void on_container_updated (MediaContainer root_container,
-                                       MediaContainer updated_container,
-                                       MediaObject object,
-                                       ObjectEventType event_type,
-                                       bool sub_tree_update) {
-        this.system_update_id++;
-        if (updated_container is TrackableContainer) {
-            this.add_last_change_entry (object, event_type, sub_tree_update);
-        }
+    private bool handle_system_update () {
         var plugin = this.root_device.resource_factory as MediaServerPlugin;
 
+        // We can increment this uint32 variable unconditionally
+        // because unsigned overflow (as compared to signed overflow)
+        // is well defined.
+        this.system_update_id++;
         if (this.system_update_id == 0 &&
             PluginCapabilities.TRACK_CHANGES in plugin.capabilities) {
             // Overflow, need to initiate Service Reset Procedure.
             // See ContentDirectory:3 spec, 2.3.7.1
             this.service_reset.begin ();
 
-            return;
+            return true;
+        }
+
+        return false;
+    }
+
+    private void handle_last_change (MediaContainer updated_container,
+                                     MediaObject object,
+                                     ObjectEventType event_type,
+                                     bool sub_tree_update) {
+        if (updated_container is TrackableContainer) {
+            this.add_last_change_entry (object, event_type, sub_tree_update);
         }
+    }
+
+    private bool set_update_ids (MediaContainer updated_container,
+                                 MediaObject object,
+                                 ObjectEventType event_type) {
+        bool container_changed = false;
 
         if (event_type == ObjectEventType.ADDED ||
-            event_type == ObjectEventType.DELETED) {
+            event_type == ObjectEventType.DELETED ||
+            (event_type == ObjectEventType.MODIFIED &&
+             object is MediaItem)) {
             updated_container.update_id = this.system_update_id;
-            object.object_update_id = this.system_update_id;
-        } else {
-            object.object_update_id = this.system_update_id;
+            container_changed = true;
+        }
+
+        object.object_update_id = this.system_update_id;
+        // Whenever container experiences object update it also
+        // experiences a container update
+        if (object is MediaContainer) {
+            (object as MediaContainer).update_id = this.system_update_id;
+        }
+
+        return container_changed;
+    }
+
+    private void handle_container_update_ids (MediaContainer? updated_container,
+                                              MediaObject object) {
+        var updated = updated_container != null;
+        var is_container = object is MediaContainer;
+
+        if (!updated && !is_container) {
+            return;
         }
 
         if (this.clear_updated_containers) {
@@ -461,8 +482,46 @@ internal class Rygel.ContentDirectory: Service {
         }
 
         // UPnP specs dicate we make sure only last update be evented
-        this.updated_containers.remove (updated_container);
-        this.updated_containers.add (updated_container);
+        if (updated) {
+            this.updated_containers.remove (updated_container);
+            this.updated_containers.add (updated_container);
+        }
+
+        if (is_container) {
+            MediaContainer container = object as MediaContainer;
+
+            this.updated_containers.remove (container);
+            this.updated_containers.add (container);
+        }
+    }
+
+    /**
+     * handler for container_updated signal on root_container. We don't
+     * immediately send the notification for changes but schedule the
+     * notification after 0.2 seconds. Also we don't clear the updated
+     * container list immediately after notification but rather in this
+     * function. Please refer to ContentDirectory version 2 specs for details
+     * on why we do all this the way we do.
+     *
+     * @param root_container the root_container
+     * @param updated_container the container that just got updated
+     */
+    private void on_container_updated (MediaContainer root_container,
+                                       MediaContainer updated_container,
+                                       MediaObject object,
+                                       ObjectEventType event_type,
+                                       bool sub_tree_update) {
+        if (handle_system_update ()) {
+            return;
+        }
+        handle_last_change (updated_container,
+                            object,
+                            event_type,
+                            sub_tree_update);
+
+        var changed = set_update_ids (updated_container, object, event_type);
+        handle_container_update_ids (changed ? updated_container : null,
+                                     object);
 
         this.ensure_timeout ();
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]