fprintf(fp, " \n");
fprintf(fp, " --clock-cycles Print timestamps in clock cycles\n");
fprintf(fp, " --clock-date Print timestamp dates\n");
- fprintf(fp, " --clock-gmt Print timestamps in GMT time zone\n");
+ fprintf(fp, " --clock-gmt Print and parse timestamps in GMT time zone\n");
fprintf(fp, " (default: local time zone)\n");
fprintf(fp, " --clock-seconds Print the timestamps as [SEC.NS]\n");
fprintf(fp, " (default format: [HH:MM:SS.NS])\n");
{
fprintf(fp, "Usage: babeltrace [OPTIONS]\n");
fprintf(fp, "\n");
- fprintf(fp, " -B, --base-begin-ns=NS Set NS as the current base beginning\n");
- fprintf(fp, " timestamp of the following source component\n");
- fprintf(fp, " instances\n");
- fprintf(fp, " -E, --base-end-ns=NS Set NS as the current base end timestamp\n");
- fprintf(fp, " of the following source component instances\n");
fprintf(fp, " -b, --base-params=PARAMS Set PARAMS as the current base parameters\n");
fprintf(fp, " of the following source and sink component\n");
fprintf(fp, " instances (see the exact format of PARAMS\n");
fprintf(fp, " below)\n");
- fprintf(fp, " --begin-ns=NS Set the beginning timestamp of the latest\n");
- fprintf(fp, " source component instance to NS\n");
fprintf(fp, " -d, --debug Enable debug mode\n");
- fprintf(fp, " --end-ns=NS Set the end timestamp of the latest source\n");
- fprintf(fp, " component instance to NS\n");
fprintf(fp, " -l, --list List available plugins and their components\n");
fprintf(fp, " -P, --path=PATH Set the `path` parameter of the latest source\n");
fprintf(fp, " or sink component to PATH\n");
fprintf(fp, " PARAMS below)\n");
fprintf(fp, " --plugin-path=PATH[:PATH]... Set paths from which dynamic plugins can be\n");
fprintf(fp, " loaded to PATH\n");
- fprintf(fp, " --reset-base-begin-ns Reset the current base beginning timestamp\n");
- fprintf(fp, " of the following source component instances\n");
- fprintf(fp, " --reset-base-end-ns Reset the current base end timestamp of the\n");
- fprintf(fp, " following source component instances\n");
fprintf(fp, " -r, --reset-base-params Reset the current base parameters of the\n");
fprintf(fp, " following source and sink component\n");
fprintf(fp, " instances to an empty map\n");
int append_sources_from_legacy_opts(GPtrArray *sources,
enum legacy_input_format legacy_input_format,
struct ctf_legacy_opts *ctf_legacy_opts,
- struct bt_value *legacy_input_paths,
- int64_t *begin_ns, int64_t *end_ns)
+ struct bt_value *legacy_input_paths)
{
int ret = 0;
int i;
}
BT_MOVE(bt_config_component->params, params);
- bt_config_component->begin.value_ns = begin_ns ? *begin_ns : 0;
- bt_config_component->begin.set = !!begin_ns;
- bt_config_component->end.value_ns = end_ns ? *end_ns : 0;
- bt_config_component->end.set = !!end_ns;
/* Move created component configuration to the array */
g_ptr_array_add(sources, bt_config_component);
return;
}
-/*
- * Validates a given source component configuration.
- */
-static
-bool validate_source_config_component(struct bt_config_component *cfg_comp)
-{
- bool valid = false;
-
- if (cfg_comp->begin.set && cfg_comp->end.set) {
- if (cfg_comp->begin.value_ns > cfg_comp->end.value_ns) {
- printf_err("Beginning timestamp (%" PRIu64 ") is greater than end timestamp (%" PRIu64 ")\n",
- cfg_comp->begin.value_ns,
- cfg_comp->end.value_ns);
- goto end;
- }
- }
-
- valid = true;
-
-end:
- return valid;
-}
-
/*
* Validates a given configuration, with optional legacy input and
* output formats options. Prints useful error messages if anything
return 0;
}
-/*
- * Parses a time in nanoseconds.
- *
- * Returns a negative value if anything goes wrong.
- */
-static
-int ns_from_arg(const char *arg, int64_t *ns)
-{
- int ret = 0;
- int64_t value;
-
- if (parse_int64(arg, &value)) {
- ret = -1;
- goto end;
- }
-
- if (value < 0) {
- ret = -1;
- goto end;
- }
-
- *ns = value;
-
-end:
- return ret;
-}
-
/* popt options */
enum {
OPT_NONE = 0,
- OPT_BASE_BEGIN_NS,
- OPT_BASE_END_NS,
OPT_BASE_PARAMS,
- OPT_BEGIN_NS,
OPT_CLOCK_CYCLES,
OPT_CLOCK_DATE,
OPT_CLOCK_FORCE_CORRELATE,
OPT_DEBUG_INFO_DIR,
OPT_DEBUG_INFO_FULL_PATH,
OPT_DEBUG_INFO_TARGET_PREFIX,
- OPT_END_NS,
OPT_FIELDS,
OPT_HELP,
OPT_HELP_LEGACY,
OPT_PATH,
OPT_PARAMS,
OPT_PLUGIN_PATH,
- OPT_RESET_BASE_BEGIN_NS,
- OPT_RESET_BASE_END_NS,
OPT_RESET_BASE_PARAMS,
OPT_SINK,
OPT_SOURCE,
/* popt long option descriptions */
static struct poptOption long_options[] = {
/* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
- { "base-begin-ns", 'B', POPT_ARG_STRING, NULL, OPT_BASE_BEGIN_NS, NULL, NULL },
- { "base-end-ns", 'E', POPT_ARG_STRING, NULL, OPT_BASE_END_NS, NULL, NULL },
{ "base-params", 'b', POPT_ARG_STRING, NULL, OPT_BASE_PARAMS, NULL, NULL },
- { "begin-ns", '\0', POPT_ARG_STRING, NULL, OPT_BEGIN_NS, NULL, NULL },
{ "clock-cycles", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_CYCLES, NULL, NULL },
{ "clock-date", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_DATE, NULL, NULL },
{ "clock-force-correlate", '\0', POPT_ARG_NONE, NULL, OPT_CLOCK_FORCE_CORRELATE, NULL, NULL },
{ "debug-info-dir", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_DIR, NULL, NULL },
{ "debug-info-full-path", 0, POPT_ARG_NONE, NULL, OPT_DEBUG_INFO_FULL_PATH, NULL, NULL },
{ "debug-info-target-prefix", 0, POPT_ARG_STRING, NULL, OPT_DEBUG_INFO_TARGET_PREFIX, NULL, NULL },
- { "end-ns", '\0', POPT_ARG_STRING, NULL, OPT_END_NS, NULL, NULL },
{ "fields", 'f', POPT_ARG_STRING, NULL, OPT_FIELDS, NULL, NULL },
{ "help", 'h', POPT_ARG_NONE, NULL, OPT_HELP, NULL, NULL },
{ "help-legacy", '\0', POPT_ARG_NONE, NULL, OPT_HELP_LEGACY, NULL, NULL },
{ "path", 'P', POPT_ARG_STRING, NULL, OPT_PATH, NULL, NULL },
{ "params", 'p', POPT_ARG_STRING, NULL, OPT_PARAMS, NULL, NULL },
{ "plugin-path", '\0', POPT_ARG_STRING, NULL, OPT_PLUGIN_PATH, NULL, NULL },
- { "reset-base-begin-ns", '\0', POPT_ARG_NONE, NULL, OPT_RESET_BASE_BEGIN_NS, NULL, NULL },
- { "reset-base-end-ns", '\0', POPT_ARG_NONE, NULL, OPT_RESET_BASE_END_NS, NULL, NULL },
{ "reset-base-params", 'r', POPT_ARG_NONE, NULL, OPT_RESET_BASE_PARAMS, NULL, NULL },
{ "sink", '\0', POPT_ARG_STRING, NULL, OPT_SINK, NULL, NULL },
{ "source", '\0', POPT_ARG_STRING, NULL, OPT_SOURCE, NULL, NULL },
*
* Return value is NULL on error, otherwise it's owned by the caller.
*/
-struct bt_config *bt_config_from_args(int argc, char *argv[], int *exit_code)
+struct bt_config *bt_config_from_args(int argc, const char *argv[], int *exit_code)
{
struct bt_config *cfg = NULL;
poptContext pc = NULL;
enum bt_config_component_dest cur_cfg_comp_dest =
BT_CONFIG_COMPONENT_DEST_SOURCE;
struct bt_value *cur_base_params = NULL;
- int64_t cur_base_begin_ns = 0;
- bool cur_base_begin_ns_set = false;
- int64_t cur_base_end_ns = 0;
- bool cur_base_end_ns_set = false;
int opt;
bool cur_cfg_comp_params_set = false;
- unsigned int i;
memset(&ctf_legacy_opts, 0, sizeof(ctf_legacy_opts));
memset(&text_legacy_opts, 0, sizeof(text_legacy_opts));
goto end;
}
- cur_cfg_comp->begin.value_ns = cur_base_begin_ns;
- cur_cfg_comp->begin.set = cur_base_begin_ns_set;
-
- cur_cfg_comp->end.value_ns = cur_base_end_ns;
- cur_cfg_comp->end.set = cur_base_end_ns_set;
-
cur_cfg_comp_dest = BT_CONFIG_COMPONENT_DEST_SOURCE;
cur_cfg_comp_params_set = false;
break;
goto error;
}
break;
- case OPT_BASE_BEGIN_NS:
- if (ns_from_arg(arg, &cur_base_begin_ns)) {
- printf_err("Invalid --base-begin-ns option's argument:\n %s\n",
- arg);
- goto error;
- }
- cur_base_begin_ns_set = true;
- break;
- case OPT_BASE_END_NS:
- if (ns_from_arg(arg, &cur_base_end_ns)) {
- printf_err("Invalid --base-end-ns option's argument:\n %s\n",
- arg);
- goto error;
- }
- cur_base_end_ns_set = true;
- break;
- case OPT_RESET_BASE_BEGIN_NS:
- cur_base_begin_ns = 0;
- cur_base_begin_ns = false;
- break;
- case OPT_RESET_BASE_END_NS:
- cur_base_end_ns = 0;
- cur_base_end_ns = false;
- break;
- case OPT_BEGIN_NS:
- if (!cur_cfg_comp || cur_cfg_comp_dest ==
- BT_CONFIG_COMPONENT_DEST_SINK) {
- printf_err("--begin-ns option must follow a --source option\n");
- goto error;
- }
-
- if (ns_from_arg(arg, &cur_cfg_comp->begin.value_ns)) {
- printf_err("Invalid --begin-ns option's argument:\n %s\n",
- arg);
- goto error;
- }
- cur_cfg_comp->begin.set = true;
- break;
- case OPT_END_NS:
- if (!cur_cfg_comp || cur_cfg_comp_dest ==
- BT_CONFIG_COMPONENT_DEST_SINK) {
- printf_err("--end-ns option must follow a --source option\n");
- goto error;
- }
-
- if (ns_from_arg(arg, &cur_cfg_comp->end.value_ns)) {
- printf_err("Invalid --end-ns option's argument:\n %s\n",
- arg);
- goto error;
- }
- cur_cfg_comp->end.set = true;
- break;
case OPT_NAMES:
if (text_legacy_opts.names) {
printf_err("Duplicate --names option\n");
if (legacy_input_format) {
if (append_sources_from_legacy_opts(cfg->sources,
legacy_input_format, &ctf_legacy_opts,
- legacy_input_paths,
- cur_base_begin_ns_set ? &cur_base_begin_ns : NULL,
- cur_base_end_ns_set ? &cur_base_end_ns : NULL)) {
+ legacy_input_paths)) {
printf_err("Cannot convert legacy input format options to source component instance(s)\n");
goto error;
}
}
}
- for (i = 0; i < cfg->sources->len; i++) {
- struct bt_config_component *cfg_component =
- bt_config_get_component(cfg->sources, i);
-
- /* Only peek */
- bt_put(cfg_component);
-
- if (!validate_source_config_component(cfg_component)) {
- printf_err("Invalid source component instance (class %s.%s)\n",
- cfg_component->plugin_name->str,
- cfg_component->component_name->str);
- goto error;
- }
- }
-
goto end;
error:
{
printf(" %s.%s\n", bt_config_component->plugin_name->str,
bt_config_component->component_name->str);
- printf(" begin timestamp: ");
-
- if (!bt_config_component->begin.set) {
- printf("not set\n");
- } else {
- printf("%" PRIu64 " ns\n", bt_config_component->begin.value_ns);
- }
-
- printf(" end timestamp: ");
-
- if (!bt_config_component->end.set) {
- printf("not set\n");
- } else {
- printf("%" PRIu64 " ns\n", bt_config_component->end.value_ns);
- }
-
printf(" params:\n");
print_value(bt_config_component->params, 6, true);
}
struct bt_component *trimmer = NULL;
struct bt_component_class *trimmer_class = NULL;
struct bt_value *trimmer_params = NULL;
+ struct bt_value *value;
assert(component_factory);
trimmer_params = bt_value_map_create();
goto end;
}
- if (source_cfg->begin.set) {
+ value = bt_value_map_get(source_cfg->params, "begin");
+ if (value) {
enum bt_value_status ret;
- struct bt_value *value;
- value = bt_value_integer_create_init(
- source_cfg->begin.value_ns);
- if (!value) {
- goto end;
- }
-
- ret = bt_value_map_insert(trimmer_params, "begin_ns_epoch",
+ ret = bt_value_map_insert(trimmer_params, "begin",
value);
BT_PUT(value);
if (ret) {
goto end;
}
}
- if (source_cfg->end.set) {
+ value = bt_value_map_get(source_cfg->params, "end");
+ if (value) {
enum bt_value_status ret;
- struct bt_value *value;
- value = bt_value_integer_create_init(
- source_cfg->end.value_ns);
- if (!value) {
+ ret = bt_value_map_insert(trimmer_params, "end",
+ value);
+ BT_PUT(value);
+ if (ret) {
goto end;
}
+ }
+ value = bt_value_map_get(source_cfg->params, "clock-gmt");
+ if (value) {
+ enum bt_value_status ret;
- ret = bt_value_map_insert(trimmer_params, "end_ns_epoch",
+ ret = bt_value_map_insert(trimmer_params, "clock-gmt",
value);
BT_PUT(value);
if (ret) {
goto end;
}
- if (source_cfg->begin.set || source_cfg->begin.set) {
+ if (bt_value_map_has_key(source_cfg->params, "begin")
+ || bt_value_map_has_key(source_cfg->params, "end")) {
/* A trimmer must be inserted in the graph. */
enum bt_component_status trimmer_status;
return ret;
}
-int main(int argc, char **argv)
+int main(int argc, const char **argv)
{
int ret;
struct bt_component_class *source_class = NULL;
destroy_trimmer_data(data);
}
+/*
+ * Parses a timestamp, figuring out its format.
+ *
+ * Returns a negative value if anything goes wrong.
+ *
+ * Expected formats:
+ *
+ * YYYY-MM-DD hh:mm:ss.ns
+ * hh:mm:ss.ns
+ * -ss.ns
+ * ss.ns
+ * YYYY-MM-DD hh:mm:ss
+ * hh:mm:ss
+ * -ss
+ * ss
+ */
static
-void init_from_params(struct trimmer *trimmer, struct bt_value *params)
+int timestamp_from_arg(const char *arg,
+ struct trimmer_bound *result_bound, bool gmt)
+{
+ int ret;
+ int64_t value;
+ unsigned int year, month, day, hh, mm, ss, ns;
+
+ /* YYYY-MM-DD hh:mm:ss.ns */
+ ret = sscanf(arg, "%u-%u-%u %u:%u:%u.%u",
+ &year, &month, &day, &hh, &mm, &ss, &ns);
+ if (ret == 7) {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = day,
+ .tm_mon = month - 1,
+ .tm_year = year - 1900,
+ .tm_isdst = -1,
+ };
+ time_t result;
+
+ if (gmt) {
+ result = timegm(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ } else {
+ result = mktime(&tm);
+ if (result < 0) {
+ return -1;
+ }
+ }
+ value = (int64_t) result;
+ value *= NSEC_PER_SEC;
+ value += ns;
+ goto set;
+ }
+ /* hh:mm:ss.ns */
+ ret = sscanf(arg, "%u:%u:%u.%u",
+ &hh, &mm, &ss, &ns);
+ if (ret == 4) {
+ /* We don't know which day until we get an event. */
+ result_bound->lazy_values.hh = hh;
+ result_bound->lazy_values.mm = mm;
+ result_bound->lazy_values.ss = ss;
+ result_bound->lazy_values.ns = ns;
+ result_bound->lazy_values.gmt = gmt;
+ goto lazy;
+ }
+ /* -ss.ns */
+ ret = sscanf(arg, "-%u.%u",
+ &ss, &ns);
+ if (ret == 2) {
+ value = -ss * NSEC_PER_SEC;
+ value -= ns;
+ goto set;
+ }
+ /* ss.ns */
+ ret = sscanf(arg, "%u.%u",
+ &ss, &ns);
+ if (ret == 2) {
+ value = ss * NSEC_PER_SEC;
+ value += ns;
+ goto set;
+ }
+
+ /* YYYY-MM-DD hh:mm:ss */
+ ret = sscanf(arg, "%u-%u-%u %u:%u:%u",
+ &year, &month, &day, &hh, &mm, &ss);
+ if (ret == 6) {
+ struct tm tm = {
+ .tm_sec = ss,
+ .tm_min = mm,
+ .tm_hour = hh,
+ .tm_mday = day,
+ .tm_mon = month - 1,
+ .tm_year = year - 1900,
+ .tm_isdst = -1,
+ };
+
+ if (gmt) {
+ value = timegm(&tm);
+ if (value < 0) {
+ return -1;
+ }
+ } else {
+ value = mktime(&tm);
+ if (value < 0) {
+ return -1;
+ }
+ }
+ value *= NSEC_PER_SEC;
+ goto set;
+ }
+ /* hh:mm:ss */
+ ret = sscanf(arg, "%u:%u:%u",
+ &hh, &mm, &ss);
+ if (ret == 3) {
+ /* We don't know which day until we get an event. */
+ result_bound->lazy_values.hh = hh;
+ result_bound->lazy_values.mm = mm;
+ result_bound->lazy_values.ss = ss;
+ result_bound->lazy_values.ns = 0;
+ result_bound->lazy_values.gmt = gmt;
+ goto lazy;
+ }
+ /* -ss */
+ ret = sscanf(arg, "-%u",
+ &ss);
+ if (ret == 1) {
+ value = -ss * NSEC_PER_SEC;
+ goto set;
+ }
+ /* ss */
+ ret = sscanf(arg, "%u",
+ &ss);
+ if (ret == 1) {
+ value = ss * NSEC_PER_SEC;
+ goto set;
+ }
+
+ /* Not found. */
+ return -1;
+
+set:
+ result_bound->value = value;
+ result_bound->set = true;
+ return 0;
+
+lazy:
+ result_bound->lazy = true;
+ return 0;
+}
+
+static
+enum bt_component_status init_from_params(struct trimmer *trimmer, struct bt_value *params)
{
struct bt_value *value = NULL;
+ bool gmt = false;
+ enum bt_component_status ret = BT_COMPONENT_STATUS_OK;
assert(params);
- value = bt_value_map_get(params, "begin_ns_epoch");
- if (value && bt_value_is_integer(value)) {
+ value = bt_value_map_get(params, "clock-gmt");
+ if (value) {
enum bt_value_status value_ret;
- value_ret = bt_value_integer_get(value, &trimmer->begin.value);
- if (!value_ret) {
- trimmer->begin.set = true;
- } else {
- printf_error("Failed to retrieve begin_ns_epoch value\n");
+ value_ret = bt_value_bool_get(value, &gmt);
+ if (value_ret) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ printf_error("Failed to retrieve clock-gmt value. Expecting a boolean.\n");
}
}
bt_put(value);
- value = bt_value_map_get(params, "end_ns_epoch");
- if (value && bt_value_is_integer(value)) {
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+
+ value = bt_value_map_get(params, "begin");
+ if (value) {
enum bt_value_status value_ret;
+ const char *str;
- value_ret = bt_value_integer_get(value, &trimmer->end.value);
- if (!value_ret) {
- trimmer->end.set = true;
- } else {
- printf_error("Failed to retrieve end_ns_epoch value\n");
+ value_ret = bt_value_string_get(value, &str);
+ if (value_ret || timestamp_from_arg(str,
+ &trimmer->begin, gmt)) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ printf_error("Failed to retrieve begin value. Expecting a timestamp string.\n");
}
}
bt_put(value);
+ if (ret != BT_COMPONENT_STATUS_OK) {
+ goto end;
+ }
+
+ value = bt_value_map_get(params, "end");
+ if (value) {
+ enum bt_value_status value_ret;
+ const char *str;
+
+ value_ret = bt_value_string_get(value, &str);
+ if (value_ret || timestamp_from_arg(str,
+ &trimmer->end, gmt)) {
+ ret = BT_COMPONENT_STATUS_INVALID;
+ printf_error("Failed to retrieve end value. Expecting a timestamp string.\n");
+ }
+ }
+ bt_put(value);
+end:
+ return ret;
}
enum bt_component_status trimmer_component_init(
goto error;
}
- init_from_params(trimmer, params);
+ ret = init_from_params(trimmer, params);
end:
return ret;
error: