* \verbatim
* LttvTracefileContext{}
* |->event\
- * | |->name (String, converted to GQuark)
- * | |->facility (String, converted to GQuark)
+ * | |->name (String, converted to GQuark) (channel.event)
+ * | |->subname (String, converted to GQuark)
* | |->category (String, not yet implemented)
* | |->time (LttTime)
* | |->tsc (LttCycleCount --> uint64)
* | |->target_pid (target PID of the event)
* | |->fields
- * | |->"facility_name
+ * | |->"channel name"
* | |->"event name"
* | |->"field name"
* | |->"sub-field name"
* | |->...
* | |->"leaf-field name" (field type)
- * |->tracefile
+ * |->channel (or tracefile)
* | |->name (String, converted to GQuark)
* |->trace
* | |->name (String, converted to GQuark)
return se;
}
+/*
+ * Keeps the array order.
+ */
+static inline gpointer ltt_g_ptr_array_remove_index_slow(GPtrArray *fp,
+ int index)
+{
+ gpointer ptr;
+ int i;
+
+ if (fp->len == 0)
+ return NULL;
+
+ ptr = g_ptr_array_index(fp, index);
+ for (i = index; i < fp->len - 1; i++) {
+ g_ptr_array_index(fp, i) = g_ptr_array_index(fp, i + 1);
+ }
+ g_ptr_array_remove_index(fp, fp->len - 1);
+ return ptr;
+}
+
/**
* @fn gboolean lttv_simple_expression_assign_field(GPtrArray*,LttvSimpleExpression*)
*
lttv_simple_expression_assign_field(GPtrArray* fp, LttvSimpleExpression* se) {
GString* f = NULL;
-
+
if(fp->len < 2) return FALSE;
- g_assert((f=g_ptr_array_remove_index(fp,0)));
-
+ g_assert((f=ltt_g_ptr_array_remove_index_slow(fp,0)));
+
+
/*
* Parse through the specified
* hardcoded fields.
* subfields, it will be considered
* as a dynamic field
*/
+
if(!g_strcasecmp(f->str,"trace") ) {
/*
* Possible values:
* trace.name
*/
g_string_free(f,TRUE);
- f=g_ptr_array_remove_index(fp,0);
+ f=ltt_g_ptr_array_remove_index_slow(fp,0);
if(!g_strcasecmp(f->str,"name")) {
se->field = LTTV_FILTER_TRACE_NAME;
}
/*
* FIXME: not yet implemented !
*/
- } else if(!g_strcasecmp(f->str,"tracefile") ) {
+ } else if(!g_strcasecmp(f->str,"tracefile")
+ || !g_strcasecmp(f->str,"channel") ) {
/*
* Possible values:
* tracefile.name
+ * channel.name
*/
g_string_free(f,TRUE);
- f=g_ptr_array_remove_index(fp,0);
+ f=ltt_g_ptr_array_remove_index_slow(fp,0);
if(!g_strcasecmp(f->str,"name")) {
se->field = LTTV_FILTER_TRACEFILE_NAME;
}
* state.cpu
*/
g_string_free(f,TRUE);
- f=g_ptr_array_remove_index(fp,0);
+ f=ltt_g_ptr_array_remove_index_slow(fp,0);
if(!g_strcasecmp(f->str,"pid") ) {
se->field = LTTV_FILTER_STATE_PID;
}
/*
* Possible values:
* event.name
+ * event.channel
* event.category
* event.time
* event.tsc
* event.field
*/
g_string_free(f,TRUE);
- f=g_ptr_array_remove_index(fp,0);
+ f=ltt_g_ptr_array_remove_index_slow(fp,0);
+
if(!g_strcasecmp(f->str,"name") ) {
se->field = LTTV_FILTER_EVENT_NAME;
}
+ else if(!g_strcasecmp(f->str,"subname") ) {
+ se->field = LTTV_FILTER_EVENT_SUBNAME;
+ }
else if(!g_strcasecmp(f->str,"category") ) {
/*
* FIXME: Category not yet functional in lttv
else if(!g_strcasecmp(f->str,"field") ) {
se->field = LTTV_FILTER_EVENT_FIELD;
g_string_free(f,TRUE);
- f=g_ptr_array_remove_index(fp,0);
+ f=ltt_g_ptr_array_remove_index_slow(fp,0);
} else {
- g_string_free(f,TRUE);
- f=g_ptr_array_remove_index(fp,0);
+ //g_string_free(f,TRUE);
+ //f=ltt_g_ptr_array_remove_index_slow(fp,0);
g_warning("Unknown event filter subtype %s", f->str);
}
} else {
g_string_free(f,TRUE);
- f=g_ptr_array_remove_index(fp,0);
+ f=ltt_g_ptr_array_remove_index_slow(fp,0);
g_warning("Unrecognized field in filter string");
}
case LTTV_FILTER_TRACEFILE_NAME:
case LTTV_FILTER_STATE_P_NAME:
case LTTV_FILTER_STATE_T_BRAND:
- case LTTV_FILTER_EVENT_NAME:
+ case LTTV_FILTER_EVENT_SUBNAME:
case LTTV_FILTER_STATE_EX_MODE:
case LTTV_FILTER_STATE_EX_SUBMODE:
case LTTV_FILTER_STATE_P_STATUS:
return FALSE;
}
break;
+ /*
+ * two strings.
+ */
+ case LTTV_FILTER_EVENT_NAME:
+ switch(op) {
+ case LTTV_FIELD_EQ:
+ se->op = lttv_apply_op_eq_quarks;
+ break;
+ case LTTV_FIELD_NE:
+ se->op = lttv_apply_op_ne_quarks;
+ break;
+ default:
+ g_warning("Error encountered in operator assignment = or != expected");
+ return FALSE;
+ }
/*
* integer
*/
case LTTV_FILTER_TRACEFILE_NAME:
case LTTV_FILTER_STATE_P_NAME:
case LTTV_FILTER_STATE_T_BRAND:
- case LTTV_FILTER_EVENT_NAME:
+ case LTTV_FILTER_EVENT_SUBNAME:
case LTTV_FILTER_STATE_EX_MODE:
case LTTV_FILTER_STATE_EX_SUBMODE:
case LTTV_FILTER_STATE_P_STATUS:
se->value.v_quark = g_quark_from_string(value);
g_free(value);
break;
+ /*
+ * Two strings.
+ */
+ case LTTV_FILTER_EVENT_NAME:
+ {
+ /* channel.event */
+ char *end = strchr(value, '.');
+ if (end) {
+ *end = '\0';
+ end++;
+ se->value.v_quarks.q[0] = g_quark_from_string(value);
+ se->value.v_quarks.q[1] = g_quark_from_string(end);
+ } else {
+ se->value.v_quarks.q[0] = (GQuark)0;
+ se->value.v_quarks.q[1] = g_quark_from_string(value);
+ }
+ g_free(value);
+ }
+ break;
/*
* integer -- supposed to be uint64
*/
case LTTV_FILTER_STATE_CT:
case LTTV_FILTER_STATE_IT:
case LTTV_FILTER_STATE_P_NAME:
- case LTTV_FILTER_STATE_T_BRAND:
+ case LTTV_FILTER_STATE_T_BRAND:
case LTTV_FILTER_STATE_EX_MODE:
case LTTV_FILTER_STATE_EX_SUBMODE:
case LTTV_FILTER_STATE_P_STATUS:
return LTTV_FILTER_STATE;
break;
case LTTV_FILTER_EVENT_NAME:
+ case LTTV_FILTER_EVENT_SUBNAME:
case LTTV_FILTER_EVENT_CATEGORY:
case LTTV_FILTER_EVENT_TIME:
case LTTV_FILTER_EVENT_TSC:
return (*r == v2.v_quark);
}
+/**
+ * @fn gboolean lttv_apply_op_eq_quarks(gpointer,LttvFieldValue)
+ *
+ * Applies the 'equal' operator to the
+ * specified structure and value
+ * @param v1 left member of comparison
+ * @param v2 right member of comparison
+ * @return success/failure of operation
+ */
+gboolean lttv_apply_op_eq_quarks(const gpointer v1, LttvFieldValue v2) {
+ GQuark *r1 = (GQuark *) v1;
+ GQuark *r2 = r1 + 1;
+ if (likely(*r1 != (GQuark)0) && *r1 != v2.v_quarks.q[0])
+ return 0;
+ if (*r2 != v2.v_quarks.q[1])
+ return 0;
+ return 1;
+}
+
/**
* @fn gboolean lttv_apply_op_eq_ltttime(gpointer,LttvFieldValue)
*
return (*r != v2.v_quark);
}
+/**
+ * @fn gboolean lttv_apply_op_ne_quarks(gpointer,LttvFieldValue)
+ *
+ * Applies the 'equal' operator to the
+ * specified structure and value
+ * @param v1 left member of comparison
+ * @param v2 right member of comparison
+ * @return success/failure of operation
+ */
+gboolean lttv_apply_op_ne_quarks(const gpointer v1, LttvFieldValue v2) {
+ GQuark *r1 = (GQuark *) v1;
+ GQuark *r2 = r1 + 1;
+ if ((*r1 == (GQuark)0 || *r1 == v2.v_quarks.q[0]) && *r2 == v2.v_quarks.q[1])
+ return 0;
+ else
+ return 1;
+}
/**
* @fn gboolean lttv_apply_op_ne_ltttime(gpointer,LttvFieldValue)
g_ptr_array_free(a_field_path,TRUE);
/* free the tree stack -- but keep the root tree */
- filter->head = g_ptr_array_remove_index(tree_stack,0);
+ filter->head = ltt_g_ptr_array_remove_index_slow(tree_stack,0);
g_ptr_array_free(tree_stack,TRUE);
/* free the field buffer if allocated */
gboolean lresult = FALSE, rresult = FALSE;
- LttvTraceState *ts;
+ LttvTraceState *ts = NULL;
LttvTracefileState *tfs = (LttvTracefileState*)context;
if(tc)
ts = (LttvTraceState*)tc;
if(event == NULL) return TRUE;
else {
struct marker_info *info;
- info = marker_get_info_from_id((LttTrace *)trace, event->event_id);
+ GQuark qtuple[2];
+ LttTracefile *tf = context->tf;
+ qtuple[0] = ltt_tracefile_name(tracefile);
+ info = marker_get_info_from_id(tf->mdata, event->event_id);
+ g_assert(info != NULL);
+ qtuple[1] = info->name;
+ return se->op((gpointer)qtuple,v);
+ }
+ break;
+ case LTTV_FILTER_EVENT_SUBNAME:
+ if(event == NULL) return TRUE;
+ else {
+ struct marker_info *info;
+ LttTracefile *tf = context->tf;
+ info = marker_get_info_from_id(tf->mdata, event->event_id);
g_assert(info != NULL);
GQuark quark = info->name;
return se->op((gpointer)&quark,v);