X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Fattribute.c;h=d06958972474cbd89909dca23ebe738a0de258e1;hb=ba576a781d5a1020ff7202ac9a959c9f4a0c7a4c;hp=973bdc9e98e4ae59afcefd8b44c549ae0a19bce6;hpb=4accaa97805e5d7fe37cb6b9f60c9e62869afdb3;p=lttv.git diff --git a/ltt/branches/poly/lttv/attribute.c b/ltt/branches/poly/lttv/attribute.c index 973bdc9e..d0695897 100644 --- a/ltt/branches/poly/lttv/attribute.c +++ b/ltt/branches/poly/lttv/attribute.c @@ -1,423 +1,305 @@ -#include "attribute.h" -inline lttv_string_id lttv_string_id_from_string(const char *s) { - return g_quark_from_string(s); -} - - -inline void lttv_string_id_release(lttv_string_id i) {} - - -inline const char *lttv_string_id_to_string(lttv_string_id i) { - return g_quark_to_string(i); -} - - -inline lttv_key *lttv_key_new() { - return g_array_new(FALSE, FALSE, sizeof(lttv_string_id)); -} - -/* Changed this function to destroy the element also, caused memory leak? */ -/* Mathieu Desnoyers */ -inline void lttv_key_destroy(lttv_key *k) { - g_array_free(k, TRUE); -} +#include +typedef union _AttributeValue { + int dv_int; + unsigned dv_uint; + long dv_long; + unsigned long dv_ulong; + float dv_float; + double dv_double; + LttvTime dv_time; + gpointer dv_pointer; + char *dv_string; + GObject *dv_gobject; +} AttributeValue; -#define _lttv_key_index(k,i) g_array_index(k, lttv_string_id, i) +typedef struct _Attribute { + LttvAttributeName name; + LttvAttributeType type; + AttributeValue value; +} Attribute; -inline void lttv_key_append(lttv_key *k, lttv_string_id i) { - g_array_append_val(k,i); -} - - -inline unsigned int lttv_key_component_number(lttv_key *k) { - return k->len; -} - - -lttv_key *lttv_key_copy(lttv_key *k) { - lttv_key *nk; - int i; - nk = lttv_key_new(); - for(i = 0 ; i < k->len ; i++) lttv_key_append(nk,lttv_key_index(k,i)); - return nk; +LttvAttributeValue address_of_value(LttvAttributeType t, AttributeValue *v) +{ + LttvAttributeValue va; + + switch(t) { + case LTTV_INT: va.v_int = &v->dv_int; break; + case LTTV_UINT: va.v_uint = &v->dv_uint; break; + case LTTV_LONG: va.v_long = &v->dv_long; break; + case LTTV_ULONG: va.v_ulong = &v->dv_ulong; break; + case LTTV_FLOAT: va.v_float = &v->dv_float; break; + case LTTV_DOUBLE: va.v_double = &v->dv_double; break; + case LTTV_TIME: va.v_time = &v->dv_time; break; + case LTTV_POINTER: va.v_pointer = &v->dv_pointer; break; + case LTTV_STRING: va.v_string = &v->dv_string; break; + case LTTV_GOBJECT: va.v_gobject = &v->dv_gobject; break; + } + return va; } -/* It is also possible to create a key directly from a pathname, - key components separated by /, (e.g., "/hooks/options/before"). */ - -lttv_key *lttv_key_new_pathname(const char *p) { - char **v, **cursor; - lttv_key *k; - v = cursor = g_strsplit(p, "/", -1); - k = lttv_key_new(); - - while(*cursor != NULL) { - lttv_key_append(k, lttv_string_id_from_string(*cursor)); - cursor++; +AttributeValue init_value(LttvAttributeType t) +{ + AttributeValue v; + + switch(t) { + case LTTV_INT: v.dv_int = 0; break; + case LTTV_UINT: v.dv_uint = 0; break; + case LTTV_LONG: v.dv_long = 0; break; + case LTTV_ULONG: v.dv_ulong = 0; break; + case LTTV_FLOAT: v.dv_float = 0; break; + case LTTV_DOUBLE: v.dv_double = 0; break; + case LTTV_TIME: v.dv_time.tv_sec = 0; v.dv_time.tv_nsec = 0; break; + case LTTV_POINTER: v.dv_pointer = NULL; break; + case LTTV_STRING: v.dv_string = NULL; break; + case LTTV_GOBJECT: v.dv_gobject = NULL; break; } - g_strfreev(v); - return k; + return v; } -static guint lttv_key_hash(gconstpointer key) { - lttv_key * k = (lttv_key *)key; - guint h = 0; - int i; - for(i = 0 ; i < k->len ; i++) h = h ^ lttv_key_index(k,i); - return h; + +unsigned int +lttv_attribute_get_number(LttvAttribute *self) +{ + return self->attributes->len; } -static gboolean lttv_key_equal(gconstpointer key1,gconstpointer key2) { - lttv_key * k1 = (lttv_key *)key1; - lttv_key * k2 = (lttv_key *)key2; - int i; - if(k1->len != k2->len) return FALSE; - for(i = 0 ; i < k1->len ; i++) - if(lttv_key_index(k1,i) != lttv_key_index(k2,i)) return FALSE; +gboolean +lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous) +{ + *homogeneous = FALSE; return TRUE; } -static void lttv_key_free(gpointer data) +LttvAttributeType +lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name, + LttvAttributeValue *v) { - lttv_key_destroy((lttv_key *)data); + Attribute *a; + + a = &g_array_index(self->attributes, Attribute, i); + *name = a->name; + *v = address_of_value(a->type, &(a->value)); + return a->type; } -static void lttv_attribute_value_free(gpointer data) +LttvAttributeType +lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name, + LttvAttributeValue *v) { - g_free(data); -} + Attribute *a; + unsigned i; -lttv_attributes *lttv_attributes_new() { - lttv_attributes *a; + gpointer p; - a = g_new(lttv_attributes, 1); - a->ints = g_hash_table_new_full(lttv_key_hash, lttv_key_equal, - lttv_key_free, lttv_attribute_value_free); - a->times = g_hash_table_new_full(lttv_key_hash, lttv_key_equal, - lttv_key_free, lttv_attribute_value_free); - a->doubles = g_hash_table_new_full(lttv_key_hash, lttv_key_equal, - lttv_key_free, lttv_attribute_value_free); - a->pointers = g_hash_table_new(lttv_key_hash, lttv_key_equal); + p = g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(p == NULL) return LTTV_NONE; - return a; + i = GPOINTER_TO_UINT(p); + i--; + a = &g_array_index(self->attributes, Attribute, i); + *v = address_of_value(a->type, &(a->value)); + return a->type; } -/* Free the hash table containing the stats and all the contained keys/vals */ - -static void lttv_attribute_key_free(gpointer k, gpointer v, gpointer data) { - lttv_key_free(k); -} - +LttvAttributeValue +lttv_attribute_add(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t) +{ + unsigned i; -void lttv_attributes_destroy(lttv_attributes *a) { - g_hash_table_destroy(a->ints); - g_hash_table_destroy(a->times); - g_hash_table_destroy(a->doubles); + Attribute a, *pa; - g_hash_table_foreach(a->pointers, lttv_attribute_key_free, NULL); - g_hash_table_destroy(a->pointers); - g_free(a); -} + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) g_error("duplicate entry in attribute table"); -unsigned int lttv_attributes_number(lttv_attributes *a) { - return g_hash_table_size(a->ints) + g_hash_table_size(a->times) + - g_hash_table_size(a->doubles) + g_hash_table_size(a->pointers); + a.name = name; + a.type = t; + a.value = init_value(t); + g_array_append_val(self->attributes, a); + i = self->attributes->len - 1; + pa = &g_array_index(self->attributes, Attribute, i); + g_hash_table_insert(self->names, GUINT_TO_POINTER(name), + GUINT_TO_POINTER(i + 1)); + return address_of_value(t, &(pa->value)); } -/* If it is a new entry, insert it in the hash table, and set it to 0 */ +/* Remove an attribute */ -int *lttv_attributes_get_integer(lttv_attributes *a, lttv_key *k) +void +lttv_attribute_remove(LttvAttribute *self, unsigned i) { - gpointer found; + Attribute *a; - found = g_hash_table_lookup(a->ints, k); - if(found == NULL) { - found = g_new(gint, 1); - *(gint *)found = 0; - g_hash_table_insert(a->ints, lttv_key_copy(k), found); - } - return found; -} + a = &g_array_index(self->attributes, Attribute, i); + /* Remove the array element and its entry in the name index */ -lttv_time *lttv_attributes_get_time(lttv_attributes *a, lttv_key *k) -{ - gpointer found; - - found = g_hash_table_lookup(a->times, k); - if(found == NULL) { - found = g_new0(lttv_time, 1); - /* *(lttv_time *)found = ZeroTime; */ - g_hash_table_insert(a->times, lttv_key_copy(k), found); - } - return found; -} + g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); + g_array_remove_index_fast(self->attributes, i); -double *lttv_attributes_get_double(lttv_attributes *a, lttv_key *k) -{ - gpointer found; + /* The element used to replace the removed element has its index entry + all wrong now. Reinsert it with its new position. */ - found = g_hash_table_lookup(a->doubles,k); - if(found == NULL) { - found = g_new(double,1); - *(double *)found = 0; - g_hash_table_insert(a->doubles, lttv_key_copy(k),found); - } - return found; + g_hash_table_remove(self->names, GUINT_TO_POINTER(a->name)); + g_hash_table_insert(self->names, GUINT_TO_POINTER(a->name), GUINT_TO_POINTER(i + 1)); } -void *lttv_attributes_get_pointer_pathname(lttv_attributes *a, char *pn) +void +lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name) { - lttv_key *key; - void *p; + unsigned i; - key = lttv_key_new_pathname(pn); - p = lttv_attributes_get_pointer(a, key); - lttv_key_destroy(key); + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i == 0) g_error("remove by name non existent attribute"); - return p; + lttv_attribute_remove(self, i - 1); } -void *lttv_attributes_get_pointer(lttv_attributes *a, lttv_key *k) -{ - return g_hash_table_lookup(a->pointers,k); -} +/* Create an empty iattribute object and add it as an attribute under the + specified name, or return an existing iattribute attribute. If an + attribute of that name already exists but is not a GObject supporting the + iattribute interface, return NULL. */ -void lttv_attributes_set_pointer_pathname(lttv_attributes *a,char *pn,void *p) +LttvIAttribute* +lttv_attribute_create_subdir(LttvAttribute *self, LttvAttributeName name) { - lttv_key *key = lttv_key_new_pathname(pn); - - lttv_attributes_set_pointer(a, key, p); - lttv_key_destroy(key); -} + unsigned i; -void lttv_attributes_set_pointer(lttv_attributes *a, lttv_key *k, void *p) { - lttv_key * oldk; - void *oldv; + Attribute a; - if(g_hash_table_lookup_extended(a->pointers, k, (gpointer)oldk, &oldv)) { - if(p == NULL) { - g_hash_table_remove(a->pointers,k); - } - else { - g_hash_table_insert(a->pointers,oldk,p); + LttvAttribute *new; + + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) { + a = g_array_index(self->attributes, Attribute, i - 1); + if(a.type == LTTV_GOBJECT && LTTV_IS_IATTRIBUTE(a.value.dv_gobject)) { + return LTTV_IATTRIBUTE(a.value.dv_gobject); } - } - else { - if(p == NULL) return; - g_hash_table_insert(a->pointers,lttv_key_copy(k),p); + else return NULL; } + new = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + *(lttv_attribute_add(self, name, LTTV_GOBJECT).v_gobject) = G_OBJECT(new); + return (LttvIAttribute *)new; } - -/* Sometimes the attributes must be accessed in bulk, sorted in different - ways. For this purpose they may be converted to arrays and sorted - multiple times. The keys used in the array belong to the lttv_attributes - object from which the array was obtained and are freed when it is - destroyed. Each element in the array is an lttv_attribute, a structure - containing the key, the value type, and a union containing a value of - that type. Multiple attributes with equal keys may be possible in some - implementations if their type differs. */ - - -typedef struct _lttv_attribute_fill_position { +gboolean +lttv_attribute_find(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t, LttvAttributeValue *v) +{ unsigned i; - lttv_attribute_type t; - lttv_attribute *a; -} lttv_attribute_fill_position; - - -static void lttv_attribute_fill(void *key, void *value, void *user_data) { - lttv_attribute_fill_position * p = (lttv_attribute_fill_position *)user_data; - lttv_attribute *a = p->a + p->i; - - a->key = (lttv_key *)key; - a->t = p->t; - switch(p->t) { - case LTTV_INTEGER: - a->v.i = *((int *)value); - case LTTV_TIME: - a->v.t = *((lttv_time *)value); - case LTTV_DOUBLE: - a->v.d = *((double *)value); - case LTTV_POINTER: - a->v.p = value; - } - p->i++; -} - -lttv_attribute *lttv_attributes_array_get(lttv_attributes *a) { - unsigned size; - lttv_attribute *v; - lttv_attribute_fill_position p; - - size = lttv_attributes_number(a); - v = g_new(lttv_attribute,size); - - p.a = v; - p.i = 0; - p.t = LTTV_INTEGER; - g_hash_table_foreach(a->ints, lttv_attribute_fill, &p); - p.t = LTTV_TIME; - g_hash_table_foreach(a->times, lttv_attribute_fill, &p); - p.t = LTTV_DOUBLE; - g_hash_table_foreach(a->doubles, lttv_attribute_fill, &p); - p.t = LTTV_POINTER; - g_hash_table_foreach(a->pointers, lttv_attribute_fill, &p); - return v; -} + Attribute *a; + i = (unsigned)g_hash_table_lookup(self->names, GUINT_TO_POINTER(name)); + if(i != 0) { + a = &g_array_index(self->attributes, Attribute, i - 1); + if(a->type != t) return FALSE; + *v = address_of_value(t, &(a->value)); + return TRUE; + } -lttv_attribute *lttv_attribute_array_destroy(lttv_attribute *a) { - g_free(a); + *v = lttv_attribute_add(self, name, t); + return TRUE; } -void lttv_attribute_array_sort(lttv_attribute *a, - unsigned size, lttv_key_compare f, - void *compare_data) +static void +attribute_interface_init (gpointer g_iface, gpointer iface_data) { - - g_qsort_with_data(a, size, sizeof(lttv_attribute), f, - compare_data); -} + LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface; + klass->get_number = (unsigned int (*) (LttvIAttribute *self)) + lttv_attribute_get_number; -int lttv_key_compare_priority(lttv_key *a, lttv_key *b, void *compare_data) -{ - int i, res; - int *priority = (int *)compare_data; + klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous)) + lttv_attribute_named; - g_assert(a->len == b->len); + klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i, + LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get; - for(i = 0 ; i < a->len ; i++) - { - res = strcmp(lttv_string_id_to_string(lttv_key_index(a,priority[i])), - lttv_string_id_to_string(lttv_key_index(a,priority[i]))); - if(res != 0) return res; - } - return 0; -} + klass->get_by_name = (LttvAttributeType (*) (LttvIAttribute *self, + LttvAttributeName name, LttvAttributeValue *v)) + lttv_attribute_get_by_name; + klass->add = (LttvAttributeValue (*) (LttvIAttribute *self, + LttvAttributeName name, LttvAttributeType t)) lttv_attribute_add; -typedef struct _select_data { - lttv_attributes *a; - lttv_key *k; - void *user_data; - lttv_key_select select; -} select_data; + klass->remove = (void (*) (LttvIAttribute *self, unsigned i)) + lttv_attribute_remove; -static void select_integer(void *key, void *value, void *user_data); -static void select_double(void *key, void *value, void *user_data); -static void select_time(void *key, void *value, void *user_data); -static void select_pointer(void *key, void *value, void *user_data); + klass->remove_by_name = (void (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_remove_by_name; -lttv_attributes *lttv_attributes_select(lttv_attributes *a, lttv_key_select f, - void *user_data) -{ - select_data *d; - - d = g_new(select_data, 1); - d->a = lttv_attributes_new(); - d->k = lttv_key_new(); - d->user_data = user_data; - d->select = f; - - g_hash_table_foreach(a->ints,select_integer, d); - g_hash_table_foreach(a->doubles,select_double, d); - g_hash_table_foreach(a->times,select_time, d); - g_hash_table_foreach(a->pointers,select_pointer, d); + klass->create_subdir = (LttvIAttribute* (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_create_subdir; } -int lttv_key_select_spec(lttv_key *in, lttv_key *out, void *user_data) -{ - lttv_key_select_spec_data *d = (lttv_key_select_spec_data *)user_data; - int i; - - /* not defined yet */ - /* lttv_key_set_size(out, 0); */ - for(i = 0 ; i < d->length ; i++) { - switch(d->spec[i]) { - case LTTV_KEEP: - break; - - case LTTV_KEEP_EQUAL: - break; - - case LTTV_KEEP_SMALLER: - break; - - case LTTV_KEEP_GREATER: - break; - - case LTTV_IGNORE: - break; - - } - } - - return 1; -} - -static void select_integer(void *key, void *value, void *user_data) +static void +attribute_instance_init (GTypeInstance *instance, gpointer g_class) { - lttv_key *k = (lttv_key *)key; - int *pi = (int *)value; - select_data *d = (select_data *)user_data; - - if(d->select(k,d->k,d->user_data)) { - *(lttv_attributes_get_integer(d->a,d->k)) += *pi; - } + LttvAttribute *self = (LttvAttribute *)instance; + self->names = g_hash_table_new(g_direct_hash, g_direct_equal); + self->attributes = g_array_new(FALSE, FALSE, sizeof(Attribute)); } -static void select_double(void *key, void *value, void *user_data) -{ - lttv_key *k = (lttv_key *)key; - double *pf = (double *)value; - select_data *d = (select_data *)user_data; - if(d->select(k,d->k,d->user_data)) { - *(lttv_attributes_get_double(d->a,d->k)) += *pf; - } +static void +attribute_finalize (LttvAttribute *self) +{ + g_hash_table_destroy(self->names); + g_array_free(self->attributes, TRUE); + G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_GET_CLASS(self)))->finalize(G_OBJECT(self)); } -static void select_time(void *key, void *value, void *user_data) + +static void +attribute_class_init (LttvAttributeClass *klass) { - lttv_key *k = (lttv_key *)key; - lttv_time *ptSum, *pt = (lttv_time *)value; - select_data *d = (select_data *)user_data; - - if(d->select(k,d->k,d->user_data)) { - ptSum = lttv_attributes_get_time(d->a,d->k); - ptSum->tv_sec += pt->tv_sec; - ptSum->tv_nsec += pt->tv_nsec; - } + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = (void (*)(GObject *self))attribute_finalize; } -static void select_pointer(void *key, void *value, void *user_data) +GType +lttv_attribute_get_type (void) { - lttv_key *k = (lttv_key *)key; - select_data *d = (select_data *)user_data; - - if(d->select(k,d->k,d->user_data)) { - lttv_attributes_set_pointer(d->a,d->k,value); + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvAttributeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) attribute_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvAttribute), + 0, /* n_preallocs */ + (GInstanceInitFunc) attribute_instance_init /* instance_init */ + }; + + static const GInterfaceInfo iattribute_info = { + (GInterfaceInitFunc) attribute_interface_init, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, "LttvAttributeType", &info, + 0); + g_type_add_interface_static (type, LTTV_IATTRIBUTE_TYPE, &iattribute_info); } + return type; } - - -