cli: automatically detect sources for leftover arguments
authorSimon Marchi <simon.marchi@efficios.com>
Fri, 5 Jul 2019 19:50:58 +0000 (15:50 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 23 Jul 2019 12:38:53 +0000 (08:38 -0400)
commit73760435c5a44d48313a85d94af093c293bc17ef
tree28738f47d3e1c6d588f05f1af9e2f724309361bc
parent32a09ecd3dfc34e9b4778905fb878f7e30fa6994
cli: automatically detect sources for leftover arguments

This patch adds a source auto-discovery feature.  The goal is for the
user to be able to just pass some inputs (which can be strings of a form
understood by a particular component class, or paths to
files/directories) and for babeltrace to figure out which component
classes are best suited to handle those inputs.

Currently, any leftover argument passed by the user is passed to a
src.ctf.fs instance.  To use a different source component, the user must
use the --component argument.  This system will therefore help usability
for users of non-src.ctf.fs sources.  It will also allow splitting the
src.ctf.fs source into a "generic CTF" one and an "LTTng CTF" one, which
includes the fixups specific to CTF files produced by various LTTng
versions.

The big picture is that for each leftover argument (called `input`), we
ask all component classes if they can handle it (see `support-info
query` below), the component classes reply with a weight, and the input
is attributed to the component class that gave the largest weight.

More precisely, this is what we do for each leftover argument:

1. Ask all known source component classes if they recognize the
   argument as an arbitrary string, which would be in a format that
   makes sense to them (but doesn't point to a file or directory on
   disk, unless it's a coincidence).  The obvious example is
   src.ctf.lttng-live, which would be apt to handle paths of the form
   'net://...'.  If some component classes claim to understand the
   argument, the one with the largest weight is chosen, and a component
   of that class will be instantiated.

2. If no component class has claimed the argument as an arbitrary
   string and the argument points to a file or directory on disk, ask
   them all if they recognize it as a file or directory they can handle.
   If some component classes do, choose the one with the biggest weight.

3. If no component class has recognized it so far, and the input points
   to a directory, we start to dig: for each child of that directory,
   apply the sophisticated algorithm described in step 2.

If a leftover argument (including all its children, if it's a directory)
is not handled by any source component class, we show a warning.  If
nothing is discovered and no explicit source is instantiated either, the
excecution fails on the "No source component" check that is already
there.

Component classes have the ability to "group" their inputs as they wish.
This means that multiple inputs attributed to a given component class
can be passed to a single instance of that class, all to separate
instances, or any combination in between.  To achieve this, component
classes are able to also reply with a group key (a string of their
choice).  Inputs with the same group key will be passed to the same
instance.

Implementation details and choices
----------------------------------

* Since leftovers are now passed to the source auto-discovery mechanism
  as opposed to an implicit src.ctf.fs component previously, this
  src.ctf.fs implicit component is no longer needed.  This changes how we
  handle some of the legacy (compatibility with babeltrace 1) flags.

  If the user passes --clock-offset or --clock-offset-ns, we will search
  in the auto-discovered sources and apply it to any src.ctf.fs instance
  created.  If no src.ctf.fs component would be instantiated, we issue
  an error.

  If the user passes --input-format ctf, we don't want other formats
  possibly being read.  We still use the auto-discovery mechanism, but
  we restrict it to the src.ctf.fs component class (other component
  classes won't be queried and therefore won't be instantiated).

* This also means that to keep the basic use case of "babeltrace2
  <dir-with-ctf-traces>" working, we need to implement the support-info
  query for the src.ctf.fs component class in the current patch.  Not
  doing so immediatly would break many tests.  The simplest possible
  implementation was added.  It looks for inputs of type "directory",
  which have a "metadata" file in it.  It always reply with the same
  group value, such that a single instance of the component class is
  used (keeping the current behavior).

* Since the strings we pass to support-info queries (and eventually to
  components we instantiate) are not necessarily paths to directories or
  files on disk (they can be URLs, for example), we now use the term
  "inputs" rather than "paths" for all of them.

* A support-info query returning ERROR aborts the auto-discovery
  process, making it return an ERROR as well.

* If we can't open a directory because we don't have permission to read
  it (EACCES), we log a warning and continue.  Other errors abort the
  auto-discovery process.

support-info query
------------------

The support-info query is a contract between the CLI and source
component classes.  Source component classes that don't support it will
simply not be able to automatically discover inputs, and will have to be
explicitly instantiated using --component.

The parameters of a support-info query are a map containing these keys:

- `type` (string): possible values are "string", "directory" or "file",
  indicating the nature of `input`, described below.  The value "string"
  means that the component class may try to interpret `input` as a
  string with a format it can recognize.  "directory" and "file"
  respectively mean to interpret `input` as a directory and file.  When
  type is "directory" or "file", the component class can assume that
  the corresponding directory or file exists on disk.
- input (string): input descriptor, to be interpreted according to
  `type`.

A support-info response can be

- A real or integer value between 0 and 1, representing the weight
- A map value containing these keys:
  - `weight` (real or integer), mandatory: between 0 and 1
  - `group` (string or null), optional: a key by which to group inputs,
    when instantiating components.

A component class that does not support a given must reply with a weight
of 0.

All inputs attributed to the same component class, sharing the same
group key, will be passed to the same component instance.  inputs whose
group key is missing or null are not grouped with other inputs.

Components created by the auto-discovery mechanism are passed the
`inputs` parameter, an array of strings containing all inputs attributed
to this instance.

testing
-------

I have a brief catch-all test for this, it just covers a few important
cases.  The test strategy is the following:

- Run babeltrace2 with an arbitrary string and a directory as
  leftovers.
- One source recognizes the arbitrary string.
- Various sources recognizes files and directories inside the passed
  directory.
- Each instantiated source outputs one line including its name and the
  sorted list of its inputs.
- We sort the output of babeltrace and compare it with an expected
  string.  Since everything is sorted, the output should be stable.

Change-Id: I7f884551d7cb576974ea53420ead9c4a8005e99d
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1644
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
26 files changed:
src/bindings/python/bt2/bt2/trace_collection_message_iterator.py
src/cli/Makefile.am
src/cli/babeltrace2-cfg-cli-args.c
src/cli/babeltrace2-cfg-src-auto-disc.c [new file with mode: 0644]
src/cli/babeltrace2-cfg-src-auto-disc.h [new file with mode: 0644]
src/cli/babeltrace2-plugins.c
src/cli/babeltrace2-plugins.h
src/cli/babeltrace2.c
src/plugins/ctf/fs-src/fs.c
src/plugins/ctf/fs-src/query.c
src/plugins/ctf/fs-src/query.h
tests/bindings/python/bt2/test_trace_collection_message_iterator.py
tests/cli/auto-source-discovery/test_auto_source_discovery [new file with mode: 0755]
tests/cli/test_convert_args
tests/data/cli/auto-source-discovery/bt_plugin_test.py [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/aaa1 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/aaa2 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/aaa3 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/bbb1 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/bbb2 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/ccc1 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/ccc2 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/ccc3 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/ccc4 [new file with mode: 0644]
tests/data/cli/auto-source-discovery/traces/some-dir/aaa10 [new file with mode: 0644]
tests/plugins/src.ctf.fs/query/test_query_trace_info.py
This page took 0.028683 seconds and 4 git commands to generate.