X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;ds=sidebyside;f=ltt%2Fbranches%2Fpoly%2Flttv%2Fattribute.c;h=6fab25dc1373605969e75bc7526a17afb0bda420;hb=dc87756342c051418eccb2b7d932ffa5453c6788;hp=b08c24da75a622ef45058263861b4b1ad3e9dd3b;hpb=c27d48bb2fe89870e0f454e8e2b6606f0c46d988;p=lttv.git diff --git a/ltt/branches/poly/lttv/attribute.c b/ltt/branches/poly/lttv/attribute.c index b08c24da..6fab25dc 100644 --- a/ltt/branches/poly/lttv/attribute.c +++ b/ltt/branches/poly/lttv/attribute.c @@ -1,424 +1,275 @@ + #include -inline lttv_string_id lttv_string_id_from_string(const char *s) { - return g_quark_from_string(s); +typedef union _AttributeValue { + int dv_int; + unsigned dv_uint; + long dv_long; + unsigned long dv_ulong; + float dv_float; + double dv_double; + timespec dv_timespec; + gpointer dv_pointer; + char *dv_string; + gobject *dv_gobject; +} AttributeValue; + + +typedef struct _Attribute { + LttvAttributeName name; + LttvAttributeType type; + AttributeValue value; +} Attribute; + + +GType +lttv_attribute_get_type (void) +{ + static GType type = 0; + if (type == 0) { + static const GTypeInfo info = { + sizeof (LttvAttributeClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + attribute_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (LttvAttribute), + 0, /* n_preallocs */ + 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; } -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); +unsigned int +lttv_attribute_get_number(LttvAttribute *self) +{ + return self->attributes->len; } -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); +gboolean +lttv_attribute_named(LttvAttribute *self, gboolean *homogeneous) +{ + *homogeneous = FALSE; + return TRUE; } -#define _lttv_key_index(k,i) g_array_index(k, lttv_string_id, i) - +LttvAttributeType +lttv_attribute_get(LttvAttribute *self, unsigned i, LttvAttributeName *name, + LttvAttributeValue *v) +{ + Attribute *a; -inline void lttv_key_append(lttv_key *k, lttv_string_id i) { - g_array_append_val(k,i); + a = &g_array_index(self->attributes, Attribute, i); + *name = a->name; + *v = address_of_value(a->type, a->value); + return a->type; } -inline unsigned int lttv_key_component_number(lttv_key *k) { - return k->len; -} +LttvAttributeType +lttv_attribute_get_by_name(LttvAttribute *self, LttvAttributeName name, + LttvAttributeValue *v) +{ + Attribute *a; + unsigned i; -lttv_key *lttv_key_copy(lttv_key *k) { - lttv_key *nk; - int i; + i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name); + if(i == 0) return LTTV_NONE; - nk = lttv_key_new(); - for(i = 0 ; i < k->len ; i++) lttv_key_append(nk,lttv_key_index(k,i)); - return nk; + i--; + a = &g_array_index(self->attributes, Attribute, i); + *v = address_of_value(a->type, a->value); + return a->type; } -/* 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++; - } - g_strfreev(v); - return k; -} +LttvAttributeValue +lttv_attribute_add(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t) +{ + unsigned i; -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; -} + Attribute a, *pa; -static gboolean lttv_key_equal(gconstpointer key1,gconstpointer key2) { - lttv_key * k1 = (lttv_key *)key1; - lttv_key * k2 = (lttv_key *)key2; - int i; + i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)name); + if(i != 0) g_error("duplicate entry in attribute table"); - 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; - return TRUE; + 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, (gconstpointer)name, (gconstpointer)i + 1); + return address_of_value(pa->value, t); } -static void lttv_key_free(gpointer data) -{ - lttv_key_destroy((lttv_key *)data); -} - +/* Remove an attribute */ -static void lttv_attribute_value_free(gpointer data) +void +lttv_attribute_remove(LttvAttribute *self, unsigned i) { - g_free(data); -} - - -lttv_attributes *lttv_attributes_new() { - lttv_attributes *a; + Attribute *a; - 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); + a = &g_array_index(self->attributes, Attribute, i); - return a; -} + /* Remove the array element and its entry in the name index */ + g_hash_table_remove(self->names, (gconspointer)a->name); + g_array_remove_index_fast(self->attributes, i); -/* Free the hash table containing the stats and all the contained keys/vals */ + /* The element used to replace the removed element has its index entry + all wrong now. Reinsert it with its new position. */ -static void lttv_attribute_key_free(gpointer k, gpointer v, gpointer data) { - lttv_key_free(k); + g_hash_table_remove(self->names, (gconstpointer)a->name); + g_hash_table_insert(self->names, (gconstpointer)a->name, i + 1); } +void +lttv_attribute_remove_by_name(LttvAttribute *self, LttvAttributeName name) +{ + 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); - - 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, (gconstpointer)name); + if(i == 0) g_error("remove by name non existent attribute"); -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); + lttv_attribute_remove(self, i - 1); } +/* 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. */ -/* If it is a new entry, insert it in the hash table, and set it to 0 */ - -int *lttv_attributes_get_integer(lttv_attributes *a, lttv_key *k) +LttvIAttribute* +lttv_attribute_create_subdir(LttvAttribute *self, LttvAttributeName name) { - gpointer found; + unsigned i; - 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; -} + Attribute a; + LttvAttribute *new; -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); + i = (unsigned)g_hash_table_lookup(self->names, (gconstpointer)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 return NULL; } - return found; + new = g_object_new(LTTV_ATTRIBUTE_TYPE); + *(lttv_attribute_add(self, name, LTTV_GOBJECT)->v_gobject) = new; + return new; } -double *lttv_attributes_get_double(lttv_attributes *a, lttv_key *k) +gboolean +lttv_attribute_find(LttvAttribute *self, LttvAttributeName name, + LttvAttributeType t, LttvAttributeValue *v) { - gpointer found; - - 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; -} + unsigned i; -void *lttv_attributes_get_pointer_pathname(lttv_attributes *a, char *pn) -{ - lttv_key *key; - void *p; + Attribute *a; - 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, (gconstpointer)name); + if(i != 0) { + a = &g_array_index(self->attributes, Attribute, i - 1); + if(a->type != t) return FALSE; + *v = address_of_value(a->value, t); + return TRUE; + } - return p; + *v = lttv_attribute_add(self, name, t); + return TRUE; } -void *lttv_attributes_get_pointer(lttv_attributes *a, lttv_key *k) -{ - return g_hash_table_lookup(a->pointers,k); -} -void lttv_attributes_set_pointer_pathname(lttv_attributes *a,char *pn,void *p) +static void +attribute_interface_init (gpointer g_iface, gpointer iface_data) { - lttv_key *key = lttv_key_new_pathname(pn); - - lttv_attributes_set_pointer(a, key, p); - lttv_key_destroy(key); -} + LttvIAttributeClass *klass = (LttvIAttributeClass *)g_iface; -void lttv_attributes_set_pointer(lttv_attributes *a, lttv_key *k, void *p) { - lttv_key * oldk; - void *oldv; + klass->get_number = (unsigned int (*) (LttvIAttribute *self)) + lttv_attribute_get_number; - 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); - } - } - else { - if(p == NULL) return; - g_hash_table_insert(a->pointers,lttv_key_copy(k),p); - } -} + klass->named = (gboolean (*) (LttvIAttribute *self, gboolean *homogeneous)) + lttv_attribute_named; + klass->get = (LttvAttributeType (*) (LttvIAttribute *self, unsigned i, + LttvAttributeName *name, LttvAttributeValue *v)) lttv_attribute_get; -#ifdef EXT_ATTRIBS -/* 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. */ + 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 _lttv_attribute_fill_position { - 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++; -} + klass->remove = (void (*) (LttvIAttribute *self, unsigned i)) + lttv_attribute_remove; + klass->remove_by_name = (void (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_remove_by_name; -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; + klass->create_subdir = (LttvIAttribute* (*) (LttvIAttribute *self, + LttvAttributeName name)) lttv_attribute_create_subdir; } -lttv_attribute *lttv_attribute_array_destroy(lttv_attribute *a) { - g_free(a); -} - - -void lttv_attribute_array_sort(lttv_attribute *a, - unsigned size, lttv_key_compare f, - void *compare_data) +static guint +quark_hash(gconstpointer key) { - - g_qsort_with_data(a, size, sizeof(lttv_attribute), f, - compare_data); + return (guint)key; } -int lttv_key_compare_priority(lttv_key *a, lttv_key *b, void *compare_data) +static gboolean +quark_equal(gconstpointer a, gconstpointer b) { - int i, res; - int *priority = (int *)compare_data; - - g_assert(a->len == b->len); - - 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; + return (a == b) } -typedef struct _select_data { - lttv_attributes *a; - lttv_key *k; - void *user_data; - lttv_key_select select; -} select_data; - -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); - -lttv_attributes *lttv_attributes_select(lttv_attributes *a, lttv_key_select f, - void *user_data) +static void +attribute_instance_init (GTypeInstance *instance, gpointer g_class) { - 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); + LttvAttribute *self = (LttvAttribute *)instance; + self->names = g_hash_table_new(quark_hash, quark_equal); + self->attributes = g_array_new(FALSE, FALSE, + sizeof(Attribute)); } -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) -{ - 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; - } -} - -static void select_double(void *key, void *value, void *user_data) +static void +attribute_finalize (LttvAttribute *self) { - 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; - } + g_hash_table_free(self->names); + g_array_free(self->attributes, TRUE); + G_OBJECT_CLASS(g_type_class_peek_parent(LTTV_ATTRIBUTE_TYPE))->finalize(self); } -static void select_time(void *key, void *value, void *user_data) -{ - 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; - } -} -static void select_pointer(void *key, void *value, void *user_data) +static void +attribute_class_init (LttvAttributeClass *klass) { - lttv_key *k = (lttv_key *)key; - select_data *d = (select_data *)user_data; + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - if(d->select(k,d->k,d->user_data)) { - lttv_attributes_set_pointer(d->a,d->k,value); - } + gobject_class->finalize = attribute_finalize; } - - - - -#endif // EXT_ATTRIBS