r7037 - in dumbhippo/trunk/client: common/ddm common/hippo linux/src
- From: commits mugshot org
- To: online-desktop-list gnome org
- Subject: r7037 - in dumbhippo/trunk/client: common/ddm common/hippo linux/src
- Date: Wed, 12 Dec 2007 09:59:21 -0600 (CST)
Author: otaylor
Date: 2007-12-12 09:59:21 -0600 (Wed, 12 Dec 2007)
New Revision: 7037
Modified:
dumbhippo/trunk/client/common/ddm/ddm-condition.c
dumbhippo/trunk/client/common/ddm/ddm-data-query.c
dumbhippo/trunk/client/common/ddm/ddm-data-resource.c
dumbhippo/trunk/client/common/ddm/ddm-data-resource.h
dumbhippo/trunk/client/common/ddm/ddm-feed.h
dumbhippo/trunk/client/common/ddm/ddm-work-item.c
dumbhippo/trunk/client/common/hippo/hippo-connection.c
dumbhippo/trunk/client/common/hippo/hippo-disk-cache.c
dumbhippo/trunk/client/linux/src/hippo-dbus-model-client.c
Log:
ddm-data-resource.[ch]: Add new value type DDM_DATA_FEED, add
ddm_data_resource_update_feed_property()
ddm-data-resource.c: Fix bug where a long value of ' ' was parsed without
error as 0.
ddm-data-query.c ddm-work-item.c: Handle recursion into feed-valued properties
ddm-condition.c: Handle feed-valued properties (not really tested, probably not
very useful, but easy enough to do)
hippo-connection.c: Parse m:ts propreties, call
ddm_data_resource_update_feed_property() as appropriate
hippo-disk-cache.c: Add an itemTimestamp column to Property (using the migration
framework for the first time), fill it in and read for it for
feed properties.
hippo-dbus-model-client.c: Add feed properties to the d-bus protocol by
using a string-long pair as the variant value
Modified: dumbhippo/trunk/client/common/ddm/ddm-condition.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-condition.c 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/ddm/ddm-condition.c 2007-12-12 15:59:21 UTC (rev 7037)
@@ -2,6 +2,7 @@
#include <string.h>
+#include "ddm-feed.h"
#include "ddm-rule.h"
static DDMCondition true_condition = {
@@ -244,6 +245,7 @@
return FALSE;
case DDM_DATA_FLOAT:
case DDM_DATA_NONE:
+ case DDM_DATA_FEED:
case DDM_DATA_LIST:
break;
}
@@ -259,15 +261,33 @@
GSList *l;
gboolean empty;
- g_return_val_if_fail(list_value->type == DDM_DATA_NONE || DDM_DATA_IS_LIST(list_value->type), FALSE);
-
- empty = list_value->type == DDM_DATA_NONE || list_value->u.list == NULL;
+ if (DDM_DATA_IS_LIST(list_value->type))
+ empty = list_value->u.list == NULL;
+ else if (list_value->type == DDM_DATA_FEED)
+ empty = list_value->u.feed == NULL || ddm_feed_is_empty(list_value->u.feed);
+ else if (list_value->type == DDM_DATA_NONE)
+ empty = TRUE;
+ else {
+ g_assert_not_reached();
+ empty = TRUE;
+ }
if (scalar_value->type == DDM_DATA_BOOLEAN)
return !empty == !!scalar_value->type;
else if (empty)
return FALSE;
- else {
+ else if (list_value->type == DDM_DATA_FEED) {
+ DDMFeedIter iter;
+ DDMDataValue element;
+
+ element.type = DDM_DATA_RESOURCE;
+
+ ddm_feed_iter_init(&iter, list_value->u.feed);
+ while (ddm_feed_iter_next(&iter, &element.u.resource, NULL)) {
+ if (compare_properties_1_1(&element, scalar_value))
+ return TRUE;
+ }
+ } else {
for (l = list_value->u.list; l; l = l->next) {
DDMDataValue element;
@@ -322,7 +342,7 @@
g_warning("Refusing to compare properties of type float");
return FALSE;
}
-
+
if (left_cardinality == DDM_DATA_CARDINALITY_N &&
right_cardinality == DDM_DATA_CARDINALITY_N) {
g_warning("Don't know how compare two list-valued properties");
@@ -370,8 +390,8 @@
return FALSE;
case DDM_DATA_FLOAT:
return FALSE;
+ case DDM_DATA_FEED:
case DDM_DATA_NONE:
- break;
case DDM_DATA_LIST:
break;
}
@@ -387,14 +407,32 @@
GSList *l;
gboolean empty;
- g_return_val_if_fail(list_value->type == DDM_DATA_NONE || DDM_DATA_IS_LIST(list_value->type), FALSE);
+ if (DDM_DATA_IS_LIST(list_value->type))
+ empty = list_value->u.list == NULL;
+ else if (list_value->type == DDM_DATA_FEED)
+ empty = list_value->u.feed == NULL || ddm_feed_is_empty(list_value->u.feed);
+ else if (list_value->type == DDM_DATA_NONE)
+ empty = TRUE;
+ else {
+ g_assert_not_reached();
+ empty = TRUE;
+ }
- empty = list_value->type == DDM_DATA_NONE || list_value->u.list == NULL;
-
if (literal->type == DDM_CONDITION_VALUE_BOOLEAN) {
return !empty == !!literal->u.boolean;
} else if (empty) {
return FALSE;
+ } else if (list_value->type == DDM_DATA_FEED) {
+ DDMFeedIter iter;
+ DDMDataValue element;
+
+ element.type = DDM_DATA_RESOURCE;
+
+ ddm_feed_iter_init(&iter, list_value->u.feed);
+ while (ddm_feed_iter_next(&iter, &element.u.resource, NULL)) {
+ if (compare_property_literal_1_1(&element, literal))
+ return TRUE;
+ }
} else {
for (l = list_value->u.list; l; l = l->next) {
DDMDataValue element;
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-query.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-query.c 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-query.c 2007-12-12 15:59:21 UTC (rev 7037)
@@ -3,6 +3,7 @@
#include "ddm-data-query-internal.h"
#include "ddm-data-model-internal.h"
#include "ddm-data-resource-internal.h"
+#include "ddm-feed.h"
typedef enum {
HANDLER_NONE,
@@ -276,6 +277,15 @@
} else {
mark_received_fetches(value.u.resource, children, local);
}
+ } else if (value.type == DDM_DATA_FEED) {
+ if (value.u.feed != NULL) {
+ DDMFeedIter feed_iter;
+ DDMDataResource *item_resource;
+
+ ddm_feed_iter_init(&feed_iter, value.u.feed);
+ while (ddm_feed_iter_next(&feed_iter, &item_resource, NULL))
+ mark_received_fetches(item_resource, children, local);
+ }
}
}
}
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-resource.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-resource.c 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-resource.c 2007-12-12 15:59:21 UTC (rev 7037)
@@ -5,6 +5,7 @@
#include <stdlib.h>
#include "ddm-data-fetch.h"
+#include "ddm-feed.h"
#include "ddm-data-model-internal.h"
#include "ddm-data-resource-internal.h"
#include "ddm-rule.h"
@@ -120,6 +121,7 @@
element->u.string = (char *)node->data;
return;
case DDM_DATA_NONE:
+ case DDM_DATA_FEED:
case DDM_DATA_LIST:
break;
}
@@ -144,6 +146,7 @@
return;
case DDM_DATA_RESOURCE:
case DDM_DATA_NONE:
+ case DDM_DATA_FEED:
case DDM_DATA_LIST:
return;
}
@@ -298,22 +301,36 @@
{
DDMDataProperty *property = data;
- if (DDM_DATA_BASE(property->value.type) != DDM_DATA_RESOURCE)
- return FALSE;
+ if (DDM_DATA_BASE(property->value.type) == DDM_DATA_RESOURCE) {
+ property->rule_sources = slist_foreach_remove(property->rule_sources, reset_resource_rule_source_foreach, property);
- property->rule_sources = slist_foreach_remove(property->rule_sources, reset_resource_rule_source_foreach, property);
-
- if (DDM_DATA_IS_LIST(property->value.type)) {
- property->value.u.list = slist_foreach_remove(property->value.u.list, reset_resource_value_foreach, NULL);
- reset_resource_value_foreach(data, user_data);
+ if (DDM_DATA_IS_LIST(property->value.type)) {
+ property->value.u.list = slist_foreach_remove(property->value.u.list, reset_resource_value_foreach, NULL);
+ reset_resource_value_foreach(data, user_data);
+ return FALSE;
+ } else {
+ if (!property->value.u.resource->local) {
+ ddm_data_property_free(property);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+ } else if (property->value.type == DDM_DATA_FEED) {
+ if (property->value.u.feed) {
+ DDMFeedIter iter;
+ DDMDataResource *resource;
+
+ ddm_feed_iter_init(&iter, property->value.u.feed);
+ while (ddm_feed_iter_next(&iter, &resource, NULL)) {
+ if (!resource->local)
+ ddm_feed_iter_remove(&iter);
+ }
+ }
+
return FALSE;
} else {
- if (!property->value.u.resource->local) {
- ddm_data_property_free(property);
- return TRUE;
- } else {
- return FALSE;
- }
+ return FALSE;
}
}
@@ -451,12 +468,16 @@
static void
set_value(DDMDataType type,
DDMDataValue *value,
- void *location)
+ void *location)
{
if (DDM_DATA_IS_LIST(type)) {
*((GSList **)location) = value->u.list;
+ } else if (type == DDM_DATA_FEED) {
+ *((DDMFeed **)location) = value->u.feed;
} else {
switch (DDM_DATA_BASE(type)) {
+ case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
case DDM_DATA_NONE:
break;
case DDM_DATA_BOOLEAN:
@@ -491,6 +512,8 @@
{
if (DDM_DATA_IS_LIST(type)) {
*((GSList **)location) = NULL;
+ } else if (type == DDM_DATA_FEED) {
+ *((DDMFeed **)location) = NULL;
} else {
switch (type) {
case DDM_DATA_BOOLEAN:
@@ -515,6 +538,7 @@
*((const char **)location) = NULL;
break;
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
case DDM_DATA_NONE:
break;
}
@@ -551,6 +575,9 @@
case DDM_DATA_URL:
result = "list:url";
break;
+ case DDM_DATA_FEED:
+ result = "xxxx:feed";
+ break;
default:
result = "list:<unknown>";
break;
@@ -829,10 +856,16 @@
case DDM_DATA_RESOURCE:
case DDM_DATA_NONE:
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
break;
}
g_slist_free(value->u.list);
+ } else if (value->type == DDM_DATA_FEED) {
+ if (value->u.feed) {
+ ddm_feed_clear(value->u.feed);
+ g_object_unref(value->u.feed);
+ }
} else {
switch (value->type) {
case DDM_DATA_NONE:
@@ -842,6 +875,7 @@
case DDM_DATA_FLOAT:
case DDM_DATA_RESOURCE:
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
break;
case DDM_DATA_STRING:
case DDM_DATA_URL:
@@ -899,6 +933,7 @@
case DDM_DATA_URL:
return strcmp(value_a->u.string, value_b->u.string) == 0;
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
break;
}
@@ -917,6 +952,11 @@
g_warning("data_property_set() called with a list type");
return FALSE;
}
+
+ if (property->value.type == DDM_DATA_FEED) {
+ g_warning("data_property_set() called with a feed type");
+ return FALSE;
+ }
if (data_value_matches(&property->value, value))
return FALSE;
@@ -971,6 +1011,7 @@
property->value.u.list = g_slist_prepend(property->value.u.list, g_strdup(value->u.string));
return;
case DDM_DATA_NONE:
+ case DDM_DATA_FEED:
case DDM_DATA_LIST:
break;
}
@@ -1063,12 +1104,23 @@
GSList *l;
gboolean changed;
+ if (value != NULL) {
+ if (DDM_DATA_IS_LIST(value->type)) {
+ g_critical("ddm_data_resource_update_property called with a list value");
+ return FALSE;
+ }
+ if (value->type == DDM_DATA_FEED) {
+ g_critical("ddm_data_resource_update_property called with a feed value");
+ return FALSE;
+ }
+ }
+
#if 0
g_debug("updating resource '%s' property %s update %d new value %s",
resource->resource_id, property_id->name, update,
value ? ddm_data_value_to_string(value) : "NULL" ); /* leak! FIXME remove from production */
-#endif
-
+#endif
+
/* it's important to only ever set this to TRUE,
* never assign it a value that could be FALSE,
* or you could unset an earlier TRUE. If making
@@ -1209,6 +1261,139 @@
return changed;
}
+/* We make things a bit more difficult for ourselves, by representing
+ * an empty feed property with:
+ *
+ * - NULL, before anything is ever added to the feed
+ * - a DDMFeed, after that
+ *
+ * The initial NULL is important because a feed that starts empty and stays
+ * empty is a common case and shouldn't require creating a DDMFeed object
+ * (think of recent messages on a block in the Mugshot stacker)
+ *
+ * Keeping the DMFeed around after that makes things a little easier for
+ * someone who wants to connect to signals on the DDFeed (though patterns
+ * to deal with the initially-NULL state probably handle transitions back
+ * to NULL OK as well.)
+ */
+static DDMDataProperty *
+add_feed_property(DDMDataResource *resource,
+ DDMQName *property_id)
+{
+ DDMDataProperty *property = add_property(resource, property_id, DDM_DATA_CARDINALITY_N);
+
+ property->value.type = DDM_DATA_FEED;
+ property->value.u.feed = NULL;
+
+ return property;
+}
+
+static gboolean
+add_feed_property_item(DDMDataProperty *property,
+ DDMDataResource *item_resource,
+ gint64 item_timestamp)
+{
+ if (property->value.u.feed == NULL)
+ property->value.u.feed = ddm_feed_new();
+
+ return ddm_feed_add_item(property->value.u.feed, item_resource, item_timestamp);
+}
+
+static void
+clear_feed_property(DDMDataProperty *property)
+{
+ if (property->value.u.feed != NULL)
+ ddm_feed_clear(property->value.u.feed);
+}
+
+/* return value is whether something changed (we need to emit notification) */
+gboolean
+ddm_data_resource_update_feed_property(DDMDataResource *resource,
+ DDMQName *property_id,
+ DDMDataUpdate update,
+ gboolean default_include,
+ const char *default_children,
+ DDMDataResource *item_resource,
+ gint64 item_timestamp)
+{
+ DDMDataProperty *property = NULL;
+ GSList *l;
+ gboolean changed;
+
+#if 0
+ g_debug("updating feed resource '%s' property %s update %d new value %s timestamp " G_GINT64_FORMAT,
+ resource->resource_id, property_id->name, update,
+ item_resource ? item_resource->resource_id : "NULL",
+ item_timestamp);
+#endif
+
+ changed = FALSE;
+
+ for (l = resource->properties; l; l = l->next) {
+ if (((DDMDataProperty *)l->data)->qname == property_id) {
+ property = l->data;
+ break;
+ }
+ }
+
+ if (update == DDM_DATA_UPDATE_DELETE && property == NULL) {
+ g_warning("Remove of a property we don't have %s#%s", property_id->uri, property_id->name);
+ return FALSE;
+ }
+
+ if (property != NULL && DDM_DATA_BASE(property->value.type) != DDM_DATA_FEED) {
+ g_warning("Previous cardinality of not compatible with new property, discarding old values %s#%s", property_id->uri, property_id->name);
+ remove_property(resource, property);
+ changed = TRUE;
+ }
+
+ switch (update) {
+ case DDM_DATA_UPDATE_ADD:
+ if (property == NULL) {
+ property = add_feed_property(resource, property_id);
+ }
+ changed = changed || add_feed_property_item(property, item_resource, item_timestamp);
+ break;
+ case DDM_DATA_UPDATE_REPLACE:
+ if (property != NULL) {
+ clear_feed_property(property);
+ } else {
+ property = add_feed_property(resource, property_id);
+ }
+ add_feed_property_item(property, item_resource, item_timestamp);
+ changed = TRUE;
+ break;
+ case DDM_DATA_UPDATE_DELETE:
+ if (property != NULL && property->value.u.feed != NULL &&
+ ddm_feed_remove_item(property->value.u.feed, item_resource))
+ {
+ changed = TRUE;
+ } else {
+ g_warning("remove of a property value not there %s#%s", property_id->uri, property_id->name);
+ }
+ break;
+ case DDM_DATA_UPDATE_CLEAR:
+ if (property != NULL) {
+ clear_feed_property(property);
+ } else {
+ property = add_feed_property(resource, property_id);
+ }
+ changed = TRUE;
+ break;
+ }
+
+ if (property != NULL) {
+ property->default_include = default_include;
+ if (default_children && !property->default_children)
+ property->default_children = ddm_data_fetch_from_string(default_children);
+ }
+
+ if (changed)
+ mark_property_changed(resource, property);
+
+ return changed;
+}
+
void
_ddm_data_resource_send_local_notifications (DDMDataResource *resource,
GSList *changed_properties)
@@ -1325,6 +1510,9 @@
case 'u':
*type = DDM_DATA_URL;
break;
+ case 'F':
+ *type = DDM_DATA_FEED;
+ break;
default:
g_warning("Can't understand type string '%s'", type_string);
return FALSE;
@@ -1384,6 +1572,32 @@
return g_string_free(str, FALSE);
}
+
+ if (value->type == DDM_DATA_FEED) {
+ GString *str = g_string_new(NULL);
+ DDMFeedIter iter;
+ DDMDataResource *resource;
+ gint64 timestamp;
+
+ g_string_append(str, "[");
+ if (value->u.feed) {
+ ddm_feed_iter_init(&iter, value->u.feed);
+
+ while (ddm_feed_iter_next(&iter, &resource, ×tamp)) {
+ if (str->len > 1)
+ g_string_append(str, ", ");
+ g_string_append(str, "(");
+ g_string_append(str, resource->resource_id);
+ g_string_append(str, ", ");
+ g_string_append_printf(str, "%" G_GINT64_FORMAT, timestamp);
+ g_string_append(str, ")");
+ }
+
+ g_string_append(str, "]");
+ }
+
+ return g_string_free(str, FALSE);
+ }
switch (value->type) {
case DDM_DATA_NONE:
@@ -1393,7 +1607,7 @@
case DDM_DATA_INTEGER:
return g_strdup_printf("%d", value->u.integer);
case DDM_DATA_LONG:
- return g_strdup_printf("%" G_GINT64_FORMAT "\n", value->u.long_);
+ return g_strdup_printf("%" G_GINT64_FORMAT, value->u.long_);
case DDM_DATA_FLOAT:
return g_strdup_printf("%f", value->u.float_);
case DDM_DATA_STRING:
@@ -1454,7 +1668,7 @@
{
char *end;
long v = strtol(str_stripped, &end, 10);
- if (*str == '\0' || *end != '\0') {
+ if (*str_stripped == '\0' || *end != '\0') {
g_set_error(error,
DDM_DATA_ERROR,
DDM_DATA_ERROR_BAD_REPLY,
@@ -1468,7 +1682,7 @@
{
char *end;
value->u.long_ = g_ascii_strtoll(str_stripped, &end, 10);
- if (*str == '\0' || *end != '\0') {
+ if (*str_stripped == '\0' || *end != '\0') {
g_set_error(error,
DDM_DATA_ERROR,
DDM_DATA_ERROR_BAD_REPLY,
@@ -1481,7 +1695,7 @@
{
char *end;
value->u.float_ = g_ascii_strtod(str_stripped, &end);
- if (*str == '\0' || *end != '\0') {
+ if (*str_stripped == '\0' || *end != '\0') {
g_set_error(error,
DDM_DATA_ERROR,
DDM_DATA_ERROR_BAD_REPLY,
@@ -1498,14 +1712,17 @@
if (value->u.string == NULL)
goto error;
goto success;
+ case DDM_DATA_FEED:
+ g_critical("Data type DDM_DATA_FEED invalid in ddm_data_value_from_string()");
+ goto error;
case DDM_DATA_RESOURCE:
g_critical("Data type DDM_DATA_RESOURCE invalid in ddm_data_value_from_string()");
goto error;
case DDM_DATA_NONE:
- g_critical("Data type DDM_DATA_RESOURCE invalid in ddm_data_value_from_string()");
+ g_critical("Data type DDM_DATA_NONE invalid in ddm_data_value_from_string()");
goto error;
case DDM_DATA_LIST:
- g_critical("Data type DDM_DATA_RESOURCE invalid in ddm_data_value_from_string()");
+ g_critical("Data type DDM_DATA_LIST invalid in ddm_data_value_from_string()");
goto error;
}
Modified: dumbhippo/trunk/client/common/ddm/ddm-data-resource.h
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-data-resource.h 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/ddm/ddm-data-resource.h 2007-12-12 15:59:21 UTC (rev 7037)
@@ -48,6 +48,7 @@
DDM_DATA_STRING = 5,
DDM_DATA_RESOURCE = 6,
DDM_DATA_URL = 7,
+ DDM_DATA_FEED = 8,
DDM_DATA_LIST = 0x10
} DDMDataType;
@@ -66,6 +67,7 @@
typedef struct _DDMDataResource DDMDataResource;
typedef struct _DDMClient DDMClient; /* Avoid circular include */
+typedef struct _DDMFeed DDMFeed;
typedef void (*DDMDataFunction) (DDMDataResource *resource,
@@ -82,6 +84,7 @@
double float_;
char *string;
DDMDataResource *resource;
+ DDMFeed *feed;
GSList *list;
} u;
};
@@ -135,6 +138,14 @@
gboolean default_include,
const char *default_children,
DDMDataValue *value);
+gboolean ddm_data_resource_update_feed_property (DDMDataResource *resource,
+ DDMQName *property_id,
+ DDMDataUpdate update,
+ gboolean default_include,
+ const char *default_children,
+ DDMDataResource *item_resource,
+ gint64 item_timestamp);
+
DDMDataProperty * ddm_data_resource_get_property (DDMDataResource *resource,
const char *name);
DDMDataProperty * ddm_data_resource_get_property_by_qname (DDMDataResource *resource,
Modified: dumbhippo/trunk/client/common/ddm/ddm-feed.h
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-feed.h 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/ddm/ddm-feed.h 2007-12-12 15:59:21 UTC (rev 7037)
@@ -25,7 +25,6 @@
* most recent item.
*/
-typedef struct _DDMFeed DDMFeed;
typedef struct _DDMFeedClass DDMFeedClass;
typedef struct _DDMFeedIter DDMFeedIter;
Modified: dumbhippo/trunk/client/common/ddm/ddm-work-item.c
===================================================================
--- dumbhippo/trunk/client/common/ddm/ddm-work-item.c 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/ddm/ddm-work-item.c 2007-12-12 15:59:21 UTC (rev 7037)
@@ -4,6 +4,7 @@
#include "ddm-data-model-internal.h"
#include "ddm-data-query-internal.h"
#include "ddm-data-resource-internal.h"
+#include "ddm-feed.h"
typedef struct {
DDMDataResource *resource;
@@ -251,6 +252,17 @@
if (!item_fetch_additional(item, value.u.resource, children))
all_satisfied = FALSE;
}
+ } else if (value.type == DDM_DATA_FEED) {
+ if (value.u.feed != NULL) {
+ DDMFeedIter feed_iter;
+ DDMDataResource *item_resource;
+
+ ddm_feed_iter_init(&feed_iter, value.u.feed);
+ while (ddm_feed_iter_next(&feed_iter, &item_resource, NULL)) {
+ if (!item_fetch_additional(item, item_resource, children))
+ all_satisfied = FALSE;
+ }
+ }
}
}
}
Modified: dumbhippo/trunk/client/common/hippo/hippo-connection.c
===================================================================
--- dumbhippo/trunk/client/common/hippo/hippo-connection.c 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/hippo/hippo-connection.c 2007-12-12 15:59:21 UTC (rev 7037)
@@ -4744,6 +4744,31 @@
return ddm_data_parse_type(type_attr, type, cardinality, default_include);
}
+static gint64
+dm_context_get_ts(DMContext *context)
+{
+ const char *ts_attr = dm_context_get_system_attribute(context, "ts");
+ if (ts_attr == NULL) {
+ return -1;
+ } else {
+ char *str_stripped;
+ char *end;
+ gint64 result;
+
+ str_stripped = g_strdup(ts_attr);
+ g_strstrip(str_stripped);
+
+ result = g_ascii_strtoll(str_stripped, &end, 10);
+ if (*str_stripped == '\0' || *end != '\0') {
+ g_warning("Invalid m:ts attribute '%s'", ts_attr);
+ result = -1;
+ }
+
+ g_free(str_stripped);
+ return result;
+ }
+}
+
static gboolean
dm_context_get_value(DMContext *context,
DDMDataType type,
@@ -4835,19 +4860,37 @@
default_children = dm_context_get_system_attribute(context, "defaultChildren");
else
default_children = NULL;
-
- if (update == DDM_DATA_UPDATE_CLEAR) {
- changed = ddm_data_resource_update_property(resource, property_qname, update, cardinality,
- default_include, default_children,
- NULL);
+
+ if (type == DDM_DATA_FEED) {
+ if (update == DDM_DATA_UPDATE_CLEAR) {
+ changed = ddm_data_resource_update_feed_property(resource, property_qname, update,
+ default_include, default_children,
+ NULL, -1);
+ } else {
+ DDMDataValue value;
+ gint64 ts = dm_context_get_ts(context);
+
+ if (dm_context_get_value(context, DDM_DATA_RESOURCE, &value)) {
+ changed = ddm_data_resource_update_feed_property(resource, property_qname, update,
+ default_include, default_children,
+ value.u.resource, ts);
+ ddm_data_value_clear(&value);
+ }
+ }
} else {
- DDMDataValue value;
-
- if (dm_context_get_value(context, type, &value)) {
+ if (update == DDM_DATA_UPDATE_CLEAR) {
changed = ddm_data_resource_update_property(resource, property_qname, update, cardinality,
default_include, default_children,
- &value);
- ddm_data_value_clear(&value);
+ NULL);
+ } else {
+ DDMDataValue value;
+
+ if (dm_context_get_value(context, type, &value)) {
+ changed = ddm_data_resource_update_property(resource, property_qname, update, cardinality,
+ default_include, default_children,
+ &value);
+ ddm_data_value_clear(&value);
+ }
}
}
Modified: dumbhippo/trunk/client/common/hippo/hippo-disk-cache.c
===================================================================
--- dumbhippo/trunk/client/common/hippo/hippo-disk-cache.c 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/common/hippo/hippo-disk-cache.c 2007-12-12 15:59:21 UTC (rev 7037)
@@ -21,7 +21,7 @@
/* Database schema version, used to know when to run upgrade steps
*/
-#define SCHEMA_VERSION 0
+#define SCHEMA_VERSION 1
static void hippo_disk_cache_init (HippoDiskCache *model);
static void hippo_disk_cache_class_init (HippoDiskCacheClass *klass);
@@ -349,6 +349,23 @@
}
}
+static gboolean
+run_migration_0_1(HippoDiskCache *cache)
+{
+ int i;
+
+ static const char *statements[] = {
+ "ALTER TABLE Property ADD COLUMN itemTimestamp INTEGER DEFAULT -1"
+ };
+
+ for (i = 0; statements[i]; i++) {
+ if (!execute_sql(cache, statements[i], NULL))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void
open_database(HippoDiskCache *cache)
{
@@ -366,7 +383,7 @@
" DELETE FROM QueryResult WHERE query = old.id; "
" END ",
"CREATE TABLE IF NOT EXISTS QueryResult (query INTEGER, resourceId TEXT)",
- "CREATE TABLE IF NOT EXISTS Property (session INTEGER, timestamp INTEGER, resourceId TEXT, propertyId TEXT, type TEXT, defaultChildren TEXT, value)",
+ "CREATE TABLE IF NOT EXISTS Property (session INTEGER, timestamp INTEGER, resourceId TEXT, propertyId TEXT, type TEXT, defaultChildren TEXT, value, itemTimestamp INTEGER DEFAULT -1)",
NULL
};
@@ -404,13 +421,9 @@
g_warning("Database version %d newer than we understand", old_version);
goto error;
} else if (old_version < SCHEMA_VERSION) {
- /* Migration steps go here
- *
- * if (old_version < 1)
- * run_migration_01(cache);
- * if (old_version < 2)
- * run_migration_12(cache);
- */
+ if (old_version < 1)
+ if (!run_migration_0_1(cache))
+ goto error;
}
}
@@ -509,6 +522,9 @@
case DDM_DATA_URL:
*(p++) = 'u';
break;
+ case DDM_DATA_FEED:
+ *(p++) = 'F';
+ break;
case DDM_DATA_NONE:
*(p++) = 's'; /* Used only for empty lists, tpye doesn't matter */
break;
@@ -618,6 +634,7 @@
value_string = value->u.string;
break;
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
case DDM_DATA_NONE:
g_assert_not_reached();
break;
@@ -661,12 +678,39 @@
NULL);
}
+static void
+save_feed_property_value_to_disk(HippoDiskCache *cache,
+ const char *resource_id,
+ const char *property_id,
+ DDMDataProperty *property,
+ DDMDataResource *resource,
+ gint64 item_timestamp,
+ const char *type,
+ const char *default_children,
+ gint64 timestamp)
+{
+ execute_sql(cache,
+ "INSERT INTO Property (session, timestamp, resourceId, propertyId, type, defaultChildren, value, itemTimestamp)"
+ " VALUES (:session, :timestamp, :resourceId, :propertyId, :type, :defaultChildren, :value, :itemTimestamp)",
+ "l:session", cache->db_session,
+ "l:timestamp", timestamp,
+ "s:resourceId", resource_id,
+ "s:propertyId", property_id,
+ "s:type", type,
+ "s:defaultChildren", default_children,
+ "s:value", ddm_data_resource_get_resource_id(resource),
+ "l:itemTimestamp", item_timestamp,
+ NULL);
+}
+
typedef struct {
DDMDataResource *resource;
DDMQName *property_qname;
DDMDataCardinality cardinality;
gboolean default_include;
char *default_children;
+ gboolean is_feed;
+ gint64 item_timestamp;
} QueuedResourceProperty;
typedef struct {
@@ -684,8 +728,10 @@
queued_resource_property_new(DDMDataResource *resource,
DDMQName *property_qname,
DDMDataCardinality cardinality,
- gboolean default_include,
- const char *default_children)
+ gboolean default_include,
+ const char *default_children,
+ gboolean is_feed,
+ gint64 item_timestamp)
{
QueuedResourceProperty *queued_property = g_new0(QueuedResourceProperty, 1);
@@ -694,6 +740,8 @@
queued_property->cardinality = cardinality;
queued_property->default_include = default_include;
queued_property->default_children = g_strdup(default_children);
+ queued_property->is_feed = is_feed;
+ queued_property->item_timestamp = item_timestamp;
return queued_property;
}
@@ -783,7 +831,7 @@
DDMQName *class_id_qname = ddm_qname_get("http://mugshot.org/p/system", "classId");
stmt = prepare_sql(cache,
- "SELECT propertyId, type,defaultChildren, value FROM Property WHERE resourceId = :resourceId",
+ "SELECT propertyId, type ,defaultChildren, value, itemTimestamp FROM Property WHERE resourceId = :resourceId",
"s:resourceId", resource_id,
NULL);
@@ -811,6 +859,8 @@
gboolean is_string = FALSE;
char *value_string = NULL;
+ gint64 item_timestamp;
+
int sql_result;
sql_result = sqlite3_step(stmt);
@@ -843,6 +893,7 @@
break;
case DDM_DATA_STRING:
case DDM_DATA_RESOURCE:
+ case DDM_DATA_FEED:
case DDM_DATA_URL:
is_string = TRUE;
break;
@@ -863,36 +914,53 @@
g_assert_not_reached();
}
+ item_timestamp = sqlite3_column_int64(stmt, 4);
+
if (cardinality == DDM_DATA_CARDINALITY_N) {
if (g_hash_table_lookup(seen_properties, property_qname) == NULL) {
g_hash_table_insert(seen_properties, property_qname, property_qname);
-
- ddm_data_resource_update_property(resource, property_qname,
- DDM_DATA_UPDATE_CLEAR,
- cardinality,
- default_include, default_children,
- NULL);
+
+ if (type == DDM_DATA_FEED)
+ ddm_data_resource_update_feed_property(resource, property_qname,
+ DDM_DATA_UPDATE_CLEAR,
+ default_include, default_children,
+ NULL, -1);
+ else
+ ddm_data_resource_update_property(resource, property_qname,
+ DDM_DATA_UPDATE_CLEAR,
+ cardinality,
+ default_include, default_children,
+ NULL);
}
}
- if (type == DDM_DATA_RESOURCE) {
+ if (type == DDM_DATA_RESOURCE || type == DDM_DATA_FEED) {
DDMDataResource *referenced_resource;
referenced_resource = resource_tracking_lookup_resource(tracking, value_string);
if (referenced_resource) {
- DDMDataValue value;
-
- value.type = type;
- value.u.resource = referenced_resource;
-
- ddm_data_resource_update_property(resource, property_qname,
- (cardinality == DDM_DATA_CARDINALITY_N) ? DDM_DATA_UPDATE_ADD : DDM_DATA_UPDATE_REPLACE,
- cardinality,
- default_include, default_children,
- &value);
+ if (type == DDM_DATA_FEED) {
+ ddm_data_resource_update_feed_property(resource, property_qname,
+ (cardinality == DDM_DATA_CARDINALITY_N) ? DDM_DATA_UPDATE_ADD : DDM_DATA_UPDATE_REPLACE,
+ default_include, default_children,
+ referenced_resource, item_timestamp);
+ } else {
+ DDMDataValue value;
+
+ value.type = type;
+ value.u.resource = referenced_resource;
+
+ ddm_data_resource_update_property(resource, property_qname,
+ (cardinality == DDM_DATA_CARDINALITY_N) ? DDM_DATA_UPDATE_ADD : DDM_DATA_UPDATE_REPLACE,
+ cardinality,
+ default_include, default_children,
+ &value);
+ }
} else {
QueuedResourceProperty *property = queued_resource_property_new(resource, property_qname,
cardinality,
- default_include, default_children);
+ default_include, default_children,
+ type == DDM_DATA_FEED,
+ item_timestamp);
resource_tracking_queue_resource(tracking, value_string, property);
}
} else {
@@ -919,6 +987,7 @@
break;
case DDM_DATA_RESOURCE:
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
case DDM_DATA_NONE:
g_assert_not_reached();
break;
@@ -1001,16 +1070,25 @@
for (properties = queued->properties; properties; properties = properties->next) {
QueuedResourceProperty *queued_property = properties->data;
- DDMDataValue value;
-
- value.type = DDM_DATA_RESOURCE;
- value.u.resource = resource;
- ddm_data_resource_update_property(queued_property->resource, queued_property->property_qname,
- (queued_property->cardinality == DDM_DATA_CARDINALITY_N) ? DDM_DATA_UPDATE_ADD : DDM_DATA_UPDATE_REPLACE,
- queued_property->cardinality,
- queued_property->default_include, queued_property->default_children,
- &value);
+ if (queued_property->is_feed) {
+ ddm_data_resource_update_feed_property(queued_property->resource, queued_property->property_qname,
+ DDM_DATA_UPDATE_ADD,
+ queued_property->default_include, queued_property->default_children,
+ resource, queued_property->item_timestamp);
+
+ } else {
+ DDMDataValue value;
+
+ value.type = DDM_DATA_RESOURCE;
+ value.u.resource = resource;
+
+ ddm_data_resource_update_property(queued_property->resource, queued_property->property_qname,
+ (queued_property->cardinality == DDM_DATA_CARDINALITY_N) ? DDM_DATA_UPDATE_ADD : DDM_DATA_UPDATE_REPLACE,
+ queued_property->cardinality,
+ queued_property->default_include, queued_property->default_children,
+ &value);
+ }
}
g_hash_table_insert(tracking->fetched_resources, g_strdup(queued->resource_id), resource);
@@ -1215,8 +1293,22 @@
char *default_children = make_default_children_string(property);
ddm_data_property_get_value(property, &value);
-
- if (ddm_data_property_get_cardinality(property) == DDM_DATA_CARDINALITY_N) {
+
+ if (value.type == DDM_DATA_FEED) {
+ if (value.u.feed != NULL) {
+ DDMFeedIter iter;
+ DDMDataResource *item_resource;
+ gint64 item_timestamp;
+
+ ddm_feed_iter_init(&iter, value.u.feed);
+ while (ddm_feed_iter_next(&iter, &item_resource, &item_timestamp)) {
+ save_feed_property_value_to_disk(cache, resource_id, property_id,
+ property,
+ item_resource, item_timestamp,
+ type, default_children, timestamp);
+ }
+ }
+ } else if (DDM_DATA_IS_LIST(value.type)) {
GSList *ll;
for (ll = value.u.list; ll; ll = ll->next) {
@@ -1227,7 +1319,7 @@
save_property_value_to_disk(cache, resource_id, property_id,
property, &element, type, default_children, timestamp);
}
- } else {
+ } else if (value.type != DDM_DATA_NONE) {
save_property_value_to_disk(cache, resource_id, property_id,
property, &value, type, default_children, timestamp);
}
Modified: dumbhippo/trunk/client/linux/src/hippo-dbus-model-client.c
===================================================================
--- dumbhippo/trunk/client/linux/src/hippo-dbus-model-client.c 2007-12-12 15:49:24 UTC (rev 7036)
+++ dumbhippo/trunk/client/linux/src/hippo-dbus-model-client.c 2007-12-12 15:59:21 UTC (rev 7037)
@@ -179,6 +179,7 @@
value_signature = "s";
break;
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
break;
}
@@ -240,6 +241,7 @@
}
break;
case DDM_DATA_LIST:
+ case DDM_DATA_FEED:
break;
}
@@ -248,6 +250,59 @@
}
static void
+add_feed_property_value_to_message(DBusMessageIter *property_array_iter,
+ DDMQName *property_qname,
+ DDMDataUpdate update,
+ DDMDataResource *item_resource,
+ gint64 item_timestamp)
+{
+ DBusMessageIter property_iter;
+ DBusMessageIter value_iter;
+ DBusMessageIter item_struct_iter;
+ char update_byte;
+ char type_byte;
+ char cardinality_byte;
+ const char *value_signature = NULL;
+ const char *item_resource_id = ddm_data_resource_get_resource_id(item_resource);
+
+ switch (update) {
+ case DDM_DATA_UPDATE_ADD:
+ update_byte = 'a';
+ break;
+ case DDM_DATA_UPDATE_REPLACE:
+ update_byte = 'r';
+ break;
+ case DDM_DATA_UPDATE_DELETE:
+ update_byte = 'd';
+ break;
+ case DDM_DATA_UPDATE_CLEAR:
+ update_byte = 'c';
+ break;
+ }
+
+ type_byte = 'F';
+ value_signature = "(sx)";
+ cardinality_byte = '*';
+
+ dbus_message_iter_open_container(property_array_iter, DBUS_TYPE_STRUCT, NULL, &property_iter);
+ dbus_message_iter_append_basic(&property_iter, DBUS_TYPE_STRING, &property_qname->uri);
+ dbus_message_iter_append_basic(&property_iter, DBUS_TYPE_STRING, &property_qname->name);
+ dbus_message_iter_append_basic(&property_iter, DBUS_TYPE_BYTE, &update_byte);
+ dbus_message_iter_append_basic(&property_iter, DBUS_TYPE_BYTE, &type_byte);
+ dbus_message_iter_append_basic(&property_iter, DBUS_TYPE_BYTE, &cardinality_byte);
+
+ dbus_message_iter_open_container(&property_iter, DBUS_TYPE_VARIANT, value_signature, &value_iter);
+
+ dbus_message_iter_open_container(&value_iter, DBUS_TYPE_STRUCT, NULL, &item_struct_iter);
+ dbus_message_iter_append_basic(&item_struct_iter, DBUS_TYPE_STRING, &item_resource_id);
+ dbus_message_iter_append_basic(&item_struct_iter, DBUS_TYPE_INT64, &item_timestamp);
+ dbus_message_iter_close_container(&value_iter, &item_struct_iter);
+
+ dbus_message_iter_close_container(&property_iter, &value_iter);
+ dbus_message_iter_close_container(property_array_iter, &property_iter);
+}
+
+static void
add_property_children_to_message(HippoDBusModelClient *client,
DBusMessageIter *resource_array_iter,
DDMDataProperty *property,
@@ -263,11 +318,19 @@
GSList *l;
for (l = value.u.list; l; l = l->next)
add_resource_to_message(client, resource_array_iter, l->data, children, TRUE, FALSE, NULL);
+ } else if (value.type == DDM_DATA_FEED && value.u.feed != NULL) {
+ DDMFeedIter feed_iter;
+ DDMDataResource *item_resource;
+
+ ddm_feed_iter_init(&feed_iter, value.u.feed);
+ while (ddm_feed_iter_next(&feed_iter, &item_resource, NULL)) {
+ add_resource_to_message(client, resource_array_iter, item_resource, children, TRUE, FALSE, NULL);
+ }
}
}
static void
-add_property_to_message(DBusMessageIter *property_array_iter,
+add_property_to_message(DBusMessageIter *property_array_iter,
DDMDataProperty *property)
{
DDMDataCardinality cardinality;
@@ -293,6 +356,22 @@
l == value.u.list ? DDM_DATA_UPDATE_REPLACE : DDM_DATA_UPDATE_ADD,
&element, cardinality);
}
+ } else if (value.type == DDM_DATA_FEED) {
+ if (value.u.feed != NULL) {
+ DDMFeedIter feed_iter;
+ DDMDataResource *item_resource;
+ gint64 item_timestamp;
+ gboolean first;
+
+ ddm_feed_iter_init(&feed_iter, value.u.feed);
+ first = TRUE;
+ while (ddm_feed_iter_next(&feed_iter, &item_resource, &item_timestamp)) {
+ add_feed_property_value_to_message(property_array_iter, property_qname,
+ first ? DDM_DATA_UPDATE_REPLACE : DDM_DATA_UPDATE_ADD,
+ item_resource, item_timestamp);
+ first = FALSE;
+ }
+ }
} else {
add_property_value_to_message(property_array_iter, property_qname,
DDM_DATA_UPDATE_REPLACE,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]