properties: return if property changed

make property_set functions return 1 if there was a change.
Only emit property change notifications when something actually
changed.
Try to only copy property value when needed.
This commit is contained in:
Wim Taymans 2018-10-04 15:18:31 +02:00
parent 0e2885b599
commit 31f4ceb137
8 changed files with 65 additions and 40 deletions

View file

@ -195,7 +195,7 @@ struct pw_client *pw_client_new(struct pw_core *core,
pw_core_add_listener(core, &impl->core_listener, &core_events, impl); pw_core_add_listener(core, &impl->core_listener, &core_events, impl);
this->info.props = this->properties ? &this->properties->dict : NULL; this->info.props = &this->properties->dict;
return this; return this;
} }
@ -321,8 +321,7 @@ void pw_client_destroy(struct pw_client *client)
pw_map_clear(&client->objects); pw_map_clear(&client->objects);
pw_array_clear(&impl->permissions); pw_array_clear(&impl->permissions);
if (client->properties) pw_properties_free(client->properties);
pw_properties_free(client->properties);
free(impl); free(impl);
} }
@ -354,20 +353,17 @@ const struct pw_client_info *pw_client_get_info(struct pw_client *client)
int pw_client_update_properties(struct pw_client *client, const struct spa_dict *dict) int pw_client_update_properties(struct pw_client *client, const struct spa_dict *dict)
{ {
struct pw_resource *resource; struct pw_resource *resource;
uint32_t i, changed = 0;
if (client->properties == NULL) { for (i = 0; i < dict->n_items; i++)
if (dict) changed += pw_properties_set(client->properties,
client->properties = pw_properties_new_dict(dict); dict->items[i].key, dict->items[i].value);
} else {
uint32_t i;
for (i = 0; i < dict->n_items; i++) if (!changed)
pw_properties_set(client->properties, return 0;
dict->items[i].key, dict->items[i].value);
}
client->info.change_mask |= PW_CLIENT_CHANGE_MASK_PROPS; client->info.change_mask |= PW_CLIENT_CHANGE_MASK_PROPS;
client->info.props = client->properties ? &client->properties->dict : NULL; client->info.props = &client->properties->dict;
pw_client_events_info_changed(client, &client->info); pw_client_events_info_changed(client, &client->info);
@ -376,7 +372,7 @@ int pw_client_update_properties(struct pw_client *client, const struct spa_dict
client->info.change_mask = 0; client->info.change_mask = 0;
return 0; return changed;
} }
struct permissions_update { struct permissions_update {

View file

@ -573,10 +573,13 @@ const struct pw_properties *pw_core_get_properties(struct pw_core *core)
int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict) int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict)
{ {
struct pw_resource *resource; struct pw_resource *resource;
uint32_t i; uint32_t i, changed = 0;
for (i = 0; i < dict->n_items; i++) for (i = 0; i < dict->n_items; i++)
pw_properties_set(core->properties, dict->items[i].key, dict->items[i].value); changed += pw_properties_set(core->properties, dict->items[i].key, dict->items[i].value);
if (!changed)
return 0;
core->info.change_mask = PW_CORE_CHANGE_MASK_PROPS; core->info.change_mask = PW_CORE_CHANGE_MASK_PROPS;
core->info.props = &core->properties->dict; core->info.props = &core->properties->dict;
@ -588,7 +591,7 @@ int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict)
core->info.change_mask = 0; core->info.change_mask = 0;
return 0; return changed;
} }
int pw_core_for_each_global(struct pw_core *core, int pw_core_for_each_global(struct pw_core *core,

View file

@ -334,10 +334,13 @@ const struct pw_properties *pw_module_get_properties(struct pw_module *module)
int pw_module_update_properties(struct pw_module *module, const struct spa_dict *dict) int pw_module_update_properties(struct pw_module *module, const struct spa_dict *dict)
{ {
struct pw_resource *resource; struct pw_resource *resource;
uint32_t i; uint32_t i, changed = 0;
for (i = 0; i < dict->n_items; i++) for (i = 0; i < dict->n_items; i++)
pw_properties_set(module->properties, dict->items[i].key, dict->items[i].value); changed += pw_properties_set(module->properties, dict->items[i].key, dict->items[i].value);
if (!changed)
return 0;
module->info.props = &module->properties->dict; module->info.props = &module->properties->dict;
@ -346,7 +349,7 @@ int pw_module_update_properties(struct pw_module *module, const struct spa_dict
pw_module_resource_info(resource, &module->info); pw_module_resource_info(resource, &module->info);
module->info.change_mask = 0; module->info.change_mask = 0;
return 0; return changed;
} }
const struct pw_module_info * const struct pw_module_info *

View file

@ -721,15 +721,19 @@ const struct pw_properties *pw_node_get_properties(struct pw_node *node)
int pw_node_update_properties(struct pw_node *node, const struct spa_dict *dict) int pw_node_update_properties(struct pw_node *node, const struct spa_dict *dict)
{ {
struct pw_resource *resource; struct pw_resource *resource;
uint32_t i; uint32_t i, changed = 0;
for (i = 0; i < dict->n_items; i++) for (i = 0; i < dict->n_items; i++)
pw_properties_set(node->properties, dict->items[i].key, dict->items[i].value); changed += pw_properties_set(node->properties, dict->items[i].key, dict->items[i].value);
pw_log_debug("node %p: updated %d properties", node, changed);
if (!changed)
return 0;
check_properties(node); check_properties(node);
node->info.props = &node->properties->dict; node->info.props = &node->properties->dict;
node->info.change_mask |= PW_NODE_CHANGE_MASK_PROPS; node->info.change_mask |= PW_NODE_CHANGE_MASK_PROPS;
pw_node_events_info_changed(node, &node->info); pw_node_events_info_changed(node, &node->info);
@ -738,7 +742,7 @@ int pw_node_update_properties(struct pw_node *node, const struct spa_dict *dict)
node->info.change_mask = 0; node->info.change_mask = 0;
return 0; return changed;
} }
static void node_done(void *data, int seq, int res) static void node_done(void *data, int seq, int res)

View file

@ -283,13 +283,17 @@ const struct pw_properties *pw_port_get_properties(struct pw_port *port)
int pw_port_update_properties(struct pw_port *port, const struct spa_dict *dict) int pw_port_update_properties(struct pw_port *port, const struct spa_dict *dict)
{ {
struct pw_resource *resource; struct pw_resource *resource;
uint32_t i; uint32_t i, changed = 0;
for (i = 0; i < dict->n_items; i++) for (i = 0; i < dict->n_items; i++)
pw_properties_set(port->properties, dict->items[i].key, dict->items[i].value); changed += pw_properties_set(port->properties, dict->items[i].key, dict->items[i].value);
pw_log_debug("port %p: updated %d properties", port, changed);
if (!changed)
return 0;
port->info.props = &port->properties->dict; port->info.props = &port->properties->dict;
port->info.change_mask |= PW_PORT_CHANGE_MASK_PROPS; port->info.change_mask |= PW_PORT_CHANGE_MASK_PROPS;
pw_port_events_info_changed(port, &port->info); pw_port_events_info_changed(port, &port->info);
@ -298,7 +302,7 @@ int pw_port_update_properties(struct pw_port *port, const struct spa_dict *dict)
port->info.change_mask = 0; port->info.change_mask = 0;
return 0; return changed;
} }
struct pw_node *pw_port_get_node(struct pw_port *port) struct pw_node *pw_port_get_node(struct pw_port *port)

View file

@ -247,31 +247,39 @@ void pw_properties_free(struct pw_properties *properties)
free(impl); free(impl);
} }
static int do_replace(struct pw_properties *properties, const char *key, char *value) static int do_replace(struct pw_properties *properties, const char *key, char *value, bool copy)
{ {
struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this); struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this);
int index = find_index(properties, key); int index = find_index(properties, key);
if (index == -1) { if (index == -1) {
add_func(properties, strdup(key), value); if (value == NULL)
return 0;
add_func(properties, strdup(key), copy ? strdup(value) : value);
} else { } else {
struct spa_dict_item *item = struct spa_dict_item *item =
pw_array_get_unchecked(&impl->items, index, struct spa_dict_item); pw_array_get_unchecked(&impl->items, index, struct spa_dict_item);
clear_item(item); if (value && strcmp(item->value, value) == 0) {
if (!copy)
free(value);
return 0;
}
if (value == NULL) { if (value == NULL) {
struct spa_dict_item *other = pw_array_get_unchecked(&impl->items, struct spa_dict_item *other = pw_array_get_unchecked(&impl->items,
pw_array_get_len(&impl->items, struct spa_dict_item) - 1, pw_array_get_len(&impl->items, struct spa_dict_item) - 1,
struct spa_dict_item); struct spa_dict_item);
clear_item(item);
item->key = other->key; item->key = other->key;
item->value = other->value; item->value = other->value;
impl->items.size -= sizeof(struct spa_dict_item); impl->items.size -= sizeof(struct spa_dict_item);
} else { } else {
item->key = strdup(key); free((char *) item->value);
item->value = value; item->value = copy ? strdup(value) : value;
} }
} }
return 0; return 1;
} }
/** Set a property value /** Set a property value
@ -279,6 +287,9 @@ static int do_replace(struct pw_properties *properties, const char *key, char *v
* \param properties the properties to change * \param properties the properties to change
* \param key a key * \param key a key
* \param value a value or NULL to remove the key * \param value a value or NULL to remove the key
* \return 1 if the properties were changed. 0 if nothing was changed because
* the property already existed with the same value or because the key to remove
* did not exist.
* *
* Set the property in \a properties with \a key to \a value. Any previous value * Set the property in \a properties with \a key to \a value. Any previous value
* of \a key will be overwritten. When \a value is NULL, the key will be * of \a key will be overwritten. When \a value is NULL, the key will be
@ -288,7 +299,7 @@ static int do_replace(struct pw_properties *properties, const char *key, char *v
*/ */
int pw_properties_set(struct pw_properties *properties, const char *key, const char *value) int pw_properties_set(struct pw_properties *properties, const char *key, const char *value)
{ {
return do_replace(properties, key, value ? strdup(value) : NULL); return do_replace(properties, key, (char*)value, true);
} }
int int
@ -297,7 +308,7 @@ pw_properties_setva(struct pw_properties *properties,
{ {
char *value; char *value;
vasprintf(&value, format, args); vasprintf(&value, format, args);
return do_replace(properties, key, value); return do_replace(properties, key, value, false);
} }
/** Set a property value by format /** Set a property value by format

View file

@ -330,16 +330,20 @@ const struct pw_properties *pw_remote_get_properties(struct pw_remote *remote)
int pw_remote_update_properties(struct pw_remote *remote, const struct spa_dict *dict) int pw_remote_update_properties(struct pw_remote *remote, const struct spa_dict *dict)
{ {
uint32_t i; uint32_t i, changed = 0;
for (i = 0; i < dict->n_items; i++) for (i = 0; i < dict->n_items; i++)
pw_properties_set(remote->properties, dict->items[i].key, dict->items[i].value); changed += pw_properties_set(remote->properties, dict->items[i].key, dict->items[i].value);
if (!changed)
return 0;
if (remote->core_proxy) if (remote->core_proxy)
pw_core_proxy_client_update(remote->core_proxy, &remote->properties->dict); pw_core_proxy_client_update(remote->core_proxy, &remote->properties->dict);
return 0; return changed;
} }
void *pw_remote_get_user_data(struct pw_remote *remote) void *pw_remote_get_user_data(struct pw_remote *remote)
{ {
return remote->user_data; return remote->user_data;

View file

@ -290,7 +290,7 @@ static void print_port(struct proxy_data *data)
if (print_all) { if (print_all) {
int i; int i;
printf(" \tdirection: \"%s\"\n", pw_direction_as_string(info->direction)); printf(" \tdirection: \"%s\"\n", pw_direction_as_string(info->direction));
printf("%c\tparams:\n", MARK_CHANGE(1)); printf("%c\tparams:\n", MARK_CHANGE(2));
for (i = 0; i < data->n_params; i++) { for (i = 0; i < data->n_params; i++) {
if (spa_pod_is_object_type(data->params[i], SPA_TYPE_OBJECT_Format)) if (spa_pod_is_object_type(data->params[i], SPA_TYPE_OBJECT_Format))
spa_debug_format(12, NULL, data->params[i]); spa_debug_format(12, NULL, data->params[i]);