master - libdm: report: add dm_report_set_selection
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=2078b842fb50d7...
Commit: 2078b842fb50d73f886fb93ff9e06c08977bf8a3
Parent: f2facdc1d01b0353b05623634d34924317c44a9c
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 12 15:04:37 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:43 2016 +0200
libdm: report: add dm_report_set_selection
Since we can do repeated dm_report_output calls now, we also like
to be able to set selection for each of these outputs.
---
WHATS_NEW_DM | 1 +
libdm/.exported_symbols.DM_1_02_128 | 1 +
libdm/libdevmapper.h | 2 +
libdm/libdm-report.c | 124 ++++++++++++++++++++++++++---------
4 files changed, 97 insertions(+), 31 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 6842771..1772e18 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.128 -
=================================
+ Add dm_report_set_selection to set selection for multiple output of report.
Add DM_REPORT_OUTPUT_MULTIPLE_TIMES flag for multiple output of same report.
Move field width handling/sort init from dm_report_object to dm_report_output.
Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
diff --git a/libdm/.exported_symbols.DM_1_02_128 b/libdm/.exported_symbols.DM_1_02_128
index 6e365d5..c323973 100644
--- a/libdm/.exported_symbols.DM_1_02_128
+++ b/libdm/.exported_symbols.DM_1_02_128
@@ -2,3 +2,4 @@ dm_report_group_create
dm_report_group_push
dm_report_group_pop
dm_report_group_destroy
+dm_report_set_selection
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index 61ab279..7fd765c 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -2675,6 +2675,8 @@ void dm_report_free(struct dm_report *rh);
int dm_report_set_output_field_name_prefix(struct dm_report *rh,
const char *report_prefix);
+int dm_report_set_selection(struct dm_report *rh, const char *selection);
+
/*
* Report functions are provided for simple data types.
* They take care of allocating copies of the data.
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 95b6ded..cae9c66 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -30,6 +30,7 @@
struct selection {
struct dm_pool *mem;
struct selection_node *selection_root;
+ int add_new_fields;
};
struct report_group_item;
@@ -1900,7 +1901,7 @@ static int _check_selection(struct dm_report *rh, struct selection_node *sn,
static int _check_report_selection(struct dm_report *rh, struct dm_list *fields)
{
- if (!rh->selection)
+ if (!rh->selection || !rh->selection->selection_root)
return 1;
return _check_selection(rh, rh->selection->selection_root, fields);
@@ -3422,9 +3423,17 @@ static struct field_selection *_create_field_selection(struct dm_report *rh,
/* The field is neither used in display options nor sort keys. */
if (!found) {
- if (!(found = _add_field(rh, field_num, implicit, FLD_HIDDEN)))
+ if (rh->selection->add_new_fields) {
+ if (!(found = _add_field(rh, field_num, implicit, FLD_HIDDEN)))
+ return NULL;
+ rh->report_types |= fields[field_num].type;
+ } else {
+ log_error("Unable to create selection with field \'%s\' "
+ "which is not included in current report.",
+ implicit ? _implicit_report_fields[field_num].id
+ : rh->fields[field_num].id);
return NULL;
- rh->report_types |= fields[field_num].type;
+ }
}
field_id = fields[found->field_num].id;
@@ -3962,6 +3971,86 @@ error:
return NULL;
}
+static int _alloc_rh_selection(struct dm_report *rh)
+{
+ if (!(rh->selection = dm_pool_zalloc(rh->mem, sizeof(struct selection))) ||
+ !(rh->selection->mem = dm_pool_create("report selection", 10 * 1024))) {
+ log_error("Failed to allocate report selection structure.");
+ if (rh->selection)
+ dm_pool_free(rh->mem, rh->selection);
+ return 0;
+ }
+
+ return 1;
+}
+
+static int _report_set_selection(struct dm_report *rh, const char *selection, int add_new_fields)
+{
+ struct selection_node *root = NULL;
+ const char *fin, *next;
+
+ if (rh->selection) {
+ if (rh->selection->selection_root)
+ /* Trash any previous selection. */
+ dm_pool_free(rh->selection->mem, rh->selection->selection_root);
+ rh->selection->selection_root = NULL;
+ } else {
+ if (!_alloc_rh_selection(rh))
+ goto_bad;
+ }
+
+ if (!selection)
+ return 1;
+
+ rh->selection->add_new_fields = add_new_fields;
+
+ if (!(root = _alloc_selection_node(rh->selection->mem, SEL_OR)))
+ return 0;
+
+ if (!_parse_or_ex(rh, selection, &fin, root))
+ goto_bad;
+
+ next = _skip_space(fin);
+ if (*next) {
+ log_error("Expecting logical operator");
+ log_error(_sel_syntax_error_at_msg, next);
+ log_error(_sel_help_ref_msg);
+ goto bad;
+ }
+
+ rh->selection->selection_root = root;
+ return 1;
+bad:
+ dm_pool_free(rh->selection->mem, root);
+ return 0;
+}
+
+static void _reset_field_props(struct dm_report *rh)
+{
+ struct field_properties *fp;
+ dm_list_iterate_items(fp, &rh->field_props)
+ fp->width = fp->initial_width;
+}
+
+int dm_report_set_selection(struct dm_report *rh, const char *selection)
+{
+ struct row *row;
+
+ if (!_report_set_selection(rh, selection, 0))
+ return_0;
+
+ _reset_field_props(rh);
+
+ dm_list_iterate_items(row, &rh->rows) {
+ row->selected = _check_report_selection(rh, &row->fields);
+ if (row->field_sel_status)
+ _implicit_report_fields[row->field_sel_status->props->field_num].report_fn(rh,
+ rh->mem, row->field_sel_status, row, rh->private);
+ }
+
+ return 1;
+}
+
struct dm_report *dm_report_init_with_selection(uint32_t *report_types,
const struct dm_report_object_type *types,
const struct dm_report_field_type *fields,
@@ -3974,8 +4063,6 @@ struct dm_report *dm_report_init_with_selection(uint32_t *report_types,
void *private_data)
{
struct dm_report *rh;
- struct selection_node *root = NULL;
- const char *fin, *next;
_implicit_report_fields = _implicit_special_report_fields_with_selection;
@@ -4005,29 +4092,11 @@ struct dm_report *dm_report_init_with_selection(uint32_t *report_types,
return rh;
}
- if (!(rh->selection = dm_pool_zalloc(rh->mem, sizeof(struct selection))) ||
- !(rh->selection->mem = dm_pool_create("report selection", 10 * 1024))) {
- log_error("Failed to allocate report selection structure.");
- goto bad;
- }
-
- if (!(root = _alloc_selection_node(rh->selection->mem, SEL_OR)))
- goto_bad;
-
- if (!_parse_or_ex(rh, selection, &fin, root))
+ if (!_report_set_selection(rh, selection, 1))
goto_bad;
- next = _skip_space(fin);
- if (*next) {
- log_error("Expecting logical operator");
- log_error(_sel_syntax_error_at_msg, next);
- log_error(_sel_help_ref_msg);
- goto bad;
- }
-
_dm_report_init_update_types(rh, report_types);
- rh->selection->selection_root = root;
return rh;
bad:
dm_report_free(rh);
@@ -4351,13 +4420,6 @@ bad:
return 0;
}
-static void _reset_field_props(struct dm_report *rh)
-{
- struct field_properties *fp;
- dm_list_iterate_items(fp, &rh->field_props)
- fp->width = fp->initial_width;
-}
-
static void _destroy_rows(struct dm_report *rh)
{
/*
7 years, 11 months
master - libdm: report: add DM_REPORT_OUTPUT_MULTIPLE_TIMES report flag to keep report data even after output is done
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f2facdc1d01b03...
Commit: f2facdc1d01b0353b05623634d34924317c44a9c
Parent: 0ba5f4b8e977a6f2f45f95777da508b42d84c01a
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 12 14:34:04 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:43 2016 +0200
libdm: report: add DM_REPORT_OUTPUT_MULTIPLE_TIMES report flag to keep report data even after output is done
The DM_REPORT_OUTPUT_MULTIPLE_TIMES instructs reporting code to
keep rows even after dm_report_output call - the rows are not
destroyed in this case which makes it possible to call dm_report_output
multiple times.
---
WHATS_NEW_DM | 1 +
libdm/libdevmapper.h | 1 +
libdm/libdm-report.c | 83 ++++++++++++++++++++++++++++++++++---------------
3 files changed, 59 insertions(+), 26 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index 7e98e1f..6842771 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.128 -
=================================
+ Add DM_REPORT_OUTPUT_MULTIPLE_TIMES flag for multiple output of same report.
Move field width handling/sort init from dm_report_object to dm_report_output.
Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
Introduce DM_REPORT_GROUP_JSON for report group with JSON output format.
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index cad79dd..61ab279 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -2606,6 +2606,7 @@ const void *dm_report_value_cache_get(struct dm_report *rh, const char *name);
#define DM_REPORT_OUTPUT_FIELD_NAME_PREFIX 0x00000008
#define DM_REPORT_OUTPUT_FIELD_UNQUOTED 0x00000010
#define DM_REPORT_OUTPUT_COLUMNS_AS_ROWS 0x00000020
+#define DM_REPORT_OUTPUT_MULTIPLE_TIMES 0x00000040
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 7a5d6e5..95b6ded 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -1994,25 +1994,35 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
if (!_check_report_selection(rh, &row->fields)) {
row->selected = 0;
- if (!row->field_sel_status)
- goto out;
-
- /*
- * If field with id "selected" is reported,
- * report the row although it does not pass
- * the selection criteria.
- * The "selected" field reports the result
- * of the selection.
- */
- _implicit_report_fields[row->field_sel_status->props->field_num].report_fn(rh,
- rh->mem, row->field_sel_status, row, rh->private);
/*
- * If the "selected" field is not displayed, e.g.
- * because it is part of the sort field list,
- * skip the display of the row as usual.
+ * If the row is not selected, we still keep it for output if either:
+ * - we're displaying special "selected" field in the row,
+ * - or the report is supposed to be on output multiple times
+ * where each output can have a new selection defined.
*/
- if (row->field_sel_status->props->flags & FLD_HIDDEN)
+ if (!row->field_sel_status && !(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
goto out;
+
+ if (row->field_sel_status) {
+ /*
+ * If field with id "selected" is reported,
+ * report the row although it does not pass
+ * the selection criteria.
+ * The "selected" field reports the result
+ * of the selection.
+ */
+ _implicit_report_fields[row->field_sel_status->props->field_num].report_fn(rh,
+ rh->mem, row->field_sel_status, row, rh->private);
+ /*
+ * If the "selected" field is not displayed, e.g.
+ * because it is part of the sort field list,
+ * skip the display of the row as usual unless
+ * we plan to do the output multiple times.
+ */
+ if ((row->field_sel_status->props->flags & FLD_HIDDEN) &&
+ !(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ goto out;
+ }
}
if (!do_output)
@@ -4165,6 +4175,11 @@ static int _row_compare(const void *a, const void *b)
return 0; /* Identical */
}
+static int _should_display_row(struct row *row)
+{
+ return row->field_sel_status || row->selected;
+}
+
static int _sort_rows(struct dm_report *rh)
{
struct row *(*rows)[];
@@ -4439,6 +4454,11 @@ static int _output_as_columns(struct dm_report *rh)
/* Print and clear buffer */
last_row = dm_list_last(&rh->rows);
dm_list_iterate_safe(rowh, rtmp, &rh->rows) {
+ row = dm_list_item(rowh, struct row);
+
+ if (!_should_display_row(row))
+ continue;
+
if (!dm_pool_begin_object(rh->mem, 512)) {
log_error("dm_report: Unable to allocate output line");
return 0;
@@ -4451,7 +4471,6 @@ static int _output_as_columns(struct dm_report *rh)
}
}
- row = dm_list_item(rowh, struct row);
do_field_delim = 0;
dm_list_iterate_safe(fh, ftmp, &row->fields) {
@@ -4478,7 +4497,8 @@ static int _output_as_columns(struct dm_report *rh)
if (!_output_field(rh, field))
goto bad;
- dm_list_del(&field->list);
+ if (!(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ dm_list_del(&field->list);
}
if (_is_json_report(rh)) {
@@ -4500,10 +4520,12 @@ static int _output_as_columns(struct dm_report *rh)
line = (char *) dm_pool_end_object(rh->mem);
log_print_bypass_report("%*s", rh->group_item ? rh->group_item->group->indent + (int) strlen(line) : 0, line);
- dm_list_del(&row->list);
+ if (!(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ dm_list_del(&row->list);
}
- _destroy_rows(rh);
+ if (!(rh->flags & DM_REPORT_OUTPUT_MULTIPLE_TIMES))
+ _destroy_rows(rh);
return 1;
@@ -4631,14 +4653,17 @@ int dm_report_output(struct dm_report *rh)
dm_list_iterate_items(row, &rh->rows) {
dm_list_iterate_items(field, &row->fields) {
- len = (int) strlen(field->report_string);
- if ((len > field->props->width))
- field->props->width = len;
-
if ((rh->flags & RH_SORT_REQUIRED) &&
(field->props->flags & FLD_SORT_KEY)) {
(*row->sort_fields)[field->props->sort_posn] = field;
}
+
+ if (_should_display_row(row)) {
+ len = (int) strlen(field->report_string);
+ if ((len > field->props->width))
+ field->props->width = len;
+
+ }
}
}
@@ -4746,8 +4771,13 @@ static int _report_group_push_single(struct report_group_item *item, void *data)
static int _report_group_push_basic(struct report_group_item *item, const char *name)
{
- if (!item->report && !name && item->parent->store.finished_count > 0)
- log_print_bypass_report("%s", "");
+ if (item->report) {
+ if (!(item->report->flags & DM_REPORT_OUTPUT_BUFFERED))
+ item->report->flags &= ~(DM_REPORT_OUTPUT_MULTIPLE_TIMES);
+ } else {
+ if (!name && item->parent->store.finished_count > 0)
+ log_print_bypass_report("%s", "");
+ }
return 1;
}
@@ -4802,6 +4832,7 @@ int dm_report_group_push(struct dm_report_group *group, struct dm_report *report
item->store.orig_report_flags = report->flags;
report->group_item = item;
}
+
item->group = group;
item->data = data;
7 years, 11 months
master - refactor: move field width calculation and sort preparation from _do_report_object to dm_report_output
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=0ba5f4b8e977a6...
Commit: 0ba5f4b8e977a6f2f45f95777da508b42d84c01a
Parent: 102cc4c1e241ee7c3f6cc8c863a06dd29f373fbc
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 12 14:07:05 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
refactor: move field width calculation and sort preparation from _do_report_object to dm_report_output
This also prepares code for repeated dm_report_output calls.
---
WHATS_NEW_DM | 1 +
libdm/libdm-report.c | 28 ++++++++++++++++------------
2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index fa4b9e6..7e98e1f 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.128 -
=================================
+ Move field width handling/sort init from dm_report_object to dm_report_output.
Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
Introduce DM_REPORT_GROUP_JSON for report group with JSON output format.
Introduce DM_REPORT_GROUP_BASIC for report group with basic report output.
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 13f2027..7a5d6e5 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -1913,7 +1913,6 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
struct row *row = NULL;
struct dm_report_field *field;
void *data = NULL;
- int len;
int r = 0;
if (!rh) {
@@ -2021,17 +2020,6 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
dm_list_add(&rh->rows, &row->list);
- dm_list_iterate_items(field, &row->fields) {
- len = (int) strlen(field->report_string);
- if ((len > field->props->width))
- field->props->width = len;
-
- if ((rh->flags & RH_SORT_REQUIRED) &&
- (field->props->flags & FLD_SORT_KEY)) {
- (*row->sort_fields)[field->props->sort_posn] = field;
- }
- }
-
if (!(rh->flags & DM_REPORT_OUTPUT_BUFFERED))
return dm_report_output(rh);
out:
@@ -4627,6 +4615,9 @@ static int _print_basic_report_header(struct dm_report *rh)
int dm_report_output(struct dm_report *rh)
{
+ struct row *row;
+ struct dm_report_field *field;
+ size_t len;
int r = 0;
if (_is_json_report(rh) &&
@@ -4638,6 +4629,19 @@ int dm_report_output(struct dm_report *rh)
goto out;
}
+ dm_list_iterate_items(row, &rh->rows) {
+ dm_list_iterate_items(field, &row->fields) {
+ len = (int) strlen(field->report_string);
+ if ((len > field->props->width))
+ field->props->width = len;
+
+ if ((rh->flags & RH_SORT_REQUIRED) &&
+ (field->props->flags & FLD_SORT_KEY)) {
+ (*row->sort_fields)[field->props->sort_posn] = field;
+ }
+ }
+ }
+
if ((rh->flags & RH_SORT_REQUIRED))
_sort_rows(rh);
7 years, 11 months
master - libdm: report: remember special field to display selection status in struct row's field_sel_status variable
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=102cc4c1e241ee...
Commit: 102cc4c1e241ee7c3f6cc8c863a06dd29f373fbc
Parent: f50d4011cdd3ef38c15b9dea05e73321592d93c2
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 12 14:03:32 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
libdm: report: remember special field to display selection status in struct row's field_sel_status variable
This allows for moving parts of the code from dm_report_object to
dm_report_output which is important for subsequent patches that allow
for repeated dm_report_output, not destroying rows on each
dm_report_output call.
---
libdm/libdm-report.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 3fa596e..13f2027 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -254,6 +254,7 @@ struct row {
struct dm_list fields; /* Fields in display order */
struct dm_report_field *(*sort_fields)[]; /* Fields in sort order */
int selected;
+ struct dm_report_field *field_sel_status;
};
/*
@@ -1910,7 +1911,7 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
const struct dm_report_field_type *fields;
struct field_properties *fp;
struct row *row = NULL;
- struct dm_report_field *field, *field_sel_status = NULL;
+ struct dm_report_field *field;
void *data = NULL;
int len;
int r = 0;
@@ -1962,7 +1963,7 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
if (fp->implicit) {
fields = _implicit_report_fields;
if (!strcmp(fields[fp->field_num].id, SPECIAL_FIELD_SELECTED_ID))
- field_sel_status = field;
+ row->field_sel_status = field;
} else
fields = rh->fields;
@@ -1994,7 +1995,7 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
if (!_check_report_selection(rh, &row->fields)) {
row->selected = 0;
- if (!field_sel_status)
+ if (!row->field_sel_status)
goto out;
/*
@@ -2004,14 +2005,14 @@ static int _do_report_object(struct dm_report *rh, void *object, int do_output,
* The "selected" field reports the result
* of the selection.
*/
- _implicit_report_fields[field_sel_status->props->field_num].report_fn(rh,
- rh->mem, field_sel_status, row, rh->private);
+ _implicit_report_fields[row->field_sel_status->props->field_num].report_fn(rh,
+ rh->mem, row->field_sel_status, row, rh->private);
/*
* If the "selected" field is not displayed, e.g.
* because it is part of the sort field list,
* skip the display of the row as usual.
*/
- if (field_sel_status->props->flags & FLD_HIDDEN)
+ if (row->field_sel_status->props->flags & FLD_HIDDEN)
goto out;
}
7 years, 11 months
master - log: also pass log_print through report and add log_print_bypass_report for use in libdm-report for direct print without report
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=f50d4011cdd3ef...
Commit: f50d4011cdd3ef38c15b9dea05e73321592d93c2
Parent: fe63715f25cf156b07e144a2e7b5cce56d32e39e
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 19 12:19:48 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
log: also pass log_print through report and add log_print_bypass_report for use in libdm-report for direct print without report
log_print is used during cmd line processing to log the result of the
operation (e.g. "Volume group vg successfully changed" and similar).
We don't want output from log_print to be interleaved with current
reports from group where log is reported as well. Also, the information
printed by log_print belongs to the log report too, so it should be
rerouted to log report if it's set.
Since the code in libdm-report which is responsible for doing the report
output uses log_print too, we need to use a different kind of log_print
which bypasses any log report currently used for logging (...simply,
we can't call log_print to output the log report itself which in turn
would again reroute to report - the report would never get on output
this way).
---
WHATS_NEW | 1 +
WHATS_NEW_DM | 1 +
lib/log/log.c | 16 +++++++++-------
lib/log/log.h | 2 ++
libdm/libdm-common.c | 2 +-
libdm/libdm-report.c | 32 ++++++++++++++++----------------
6 files changed, 30 insertions(+), 24 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 88e785a..823eeaf 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Also pass common printed messages (besides warnings and errors) to log report.
Log warnings and errors via report during cmd processing if this is enabled.
Make it possible to iterate over internal 'orphan' VGs in process_each_vg fn.
Make -S|--select option groupable that allows this option to be repeated.
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index da36f49..fa4b9e6 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.128 -
=================================
+ Add _LOG_BYPASS_REPORT flag for bypassing any log report currently set.
Introduce DM_REPORT_GROUP_JSON for report group with JSON output format.
Introduce DM_REPORT_GROUP_BASIC for report group with basic report output.
Introduce DM_REPORT_GROUP_SINGLE for report group having single report only.
diff --git a/lib/log/log.c b/lib/log/log.c
index 3181fdd..0bd2de9 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -270,7 +270,7 @@ void reset_log_duplicated(void) {
}
}
-static const char *_get_log_level_name(int level)
+static const char *_get_log_level_name(int use_stderr, int level)
{
static const char *log_level_names[] = {"", /* unassigned */
"", /* unassigned */
@@ -281,7 +281,9 @@ static const char *_get_log_level_name(int level)
"info", /* _LOG_INFO */
"debug" /* _LOG_DEBUG */
};
- level &= ~_LOG_STDERR;
+ if (level == _LOG_WARN && !use_stderr)
+ return "print";
+
return log_level_names[level];
}
@@ -312,6 +314,7 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
char *newbuf;
int use_stderr = level & _LOG_STDERR;
int log_once = level & _LOG_ONCE;
+ int log_bypass_report = level & _LOG_BYPASS_REPORT;
int fatal_internal_error = 0;
size_t msglen;
const char *indent_spaces = "";
@@ -322,7 +325,7 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
struct dm_report *orig_report;
int logged_via_report = 0;
- level &= ~(_LOG_STDERR|_LOG_ONCE);
+ level &= ~(_LOG_STDERR|_LOG_ONCE|_LOG_BYPASS_REPORT);
if (_abort_on_internal_errors_env_present < 0) {
if ((env_str = getenv("DM_ABORT_ON_INTERNAL_ERRORS"))) {
@@ -353,7 +356,7 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
if (_lvm2_log_fn ||
(_store_errmsg && (level <= _LOG_ERR)) ||
- (_log_report.report && (use_stderr || (level <=_LOG_ERR))) ||
+ (_log_report.report && !log_bypass_report && (use_stderr || (level <=_LOG_WARN))) ||
log_once) {
va_start(ap, format);
n = vsnprintf(message, sizeof(message), trformat, ap);
@@ -401,11 +404,10 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
}
}
- if (_log_report.report && (use_stderr || (level <= _LOG_ERR))) {
+ if (_log_report.report && !log_bypass_report && (use_stderr || (level <= _LOG_WARN))) {
orig_report = _log_report.report;
_log_report.report = NULL;
-
- if (!report_cmdlog(orig_report, _get_log_level_name(level),
+ if (!report_cmdlog(orig_report, _get_log_level_name(use_stderr, level),
log_get_report_context_name(_log_report.context),
log_get_report_object_type_name(_log_report.object_type),
_log_report.object_name, _log_report.object_id,
diff --git a/lib/log/log.h b/lib/log/log.h
index 222a1ad..15d363e 100644
--- a/lib/log/log.h
+++ b/lib/log/log.h
@@ -44,6 +44,7 @@
#define _LOG_STDERR 128 /* force things to go to stderr, even if loglevel
would make them go to stdout */
#define _LOG_ONCE 256 /* downgrade to NOTICE if this has been already logged */
+#define _LOG_BYPASS_REPORT 512 /* do not log through report even if report available */
#define _LOG_DEBUG 7
#define _LOG_INFO 6
#define _LOG_NOTICE 5
@@ -93,6 +94,7 @@
#define log_very_verbose(args...) log_info(args)
#define log_verbose(args...) log_notice(args)
#define log_print(args...) LOG_LINE(_LOG_WARN, args)
+#define log_print_bypass_report(args...) LOG_LINE(_LOG_WARN | _LOG_BYPASS_REPORT, args)
#define log_print_unless_silent(args...) LOG_LINE(silent_mode() ? _LOG_NOTICE : _LOG_WARN, args)
#define log_error(args...) log_err(args)
#define log_error_suppress(s, args...) log_err_suppress(s, args)
diff --git a/libdm/libdm-common.c b/libdm/libdm-common.c
index d67d0bb..6ac936f 100644
--- a/libdm/libdm-common.c
+++ b/libdm/libdm-common.c
@@ -116,7 +116,7 @@ static void _default_log_line(int level,
static int _abort_on_internal_errors = -1;
FILE *out = (level & _LOG_STDERR) ? stderr : stdout;
- level &= ~_LOG_STDERR;
+ level &= ~(_LOG_STDERR | _LOG_BYPASS_REPORT);
if (level <= _LOG_WARN || _verbose) {
if (level < _LOG_WARN)
diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c
index 485bbdf..3fa596e 100644
--- a/libdm/libdm-report.c
+++ b/libdm/libdm-report.c
@@ -4105,7 +4105,7 @@ static int _report_headings(struct dm_report *rh)
/* print all headings */
heading = (char *) dm_pool_end_object(rh->mem);
- log_print("%s", heading);
+ log_print_bypass_report("%s", heading);
dm_pool_free(rh->mem, (void *)heading);
dm_free(buf);
@@ -4422,7 +4422,7 @@ static int _output_as_rows(struct dm_report *rh)
log_error("dm_report: Failed to terminate row");
goto bad;
}
- log_print("%s", (char *) dm_pool_end_object(rh->mem));
+ log_print_bypass_report("%s", (char *) dm_pool_end_object(rh->mem));
}
_destroy_rows(rh);
@@ -4510,7 +4510,7 @@ static int _output_as_columns(struct dm_report *rh)
}
line = (char *) dm_pool_end_object(rh->mem);
- log_print("%*s", rh->group_item ? rh->group_item->group->indent + (int) strlen(line) : 0, line);
+ log_print_bypass_report("%*s", rh->group_item ? rh->group_item->group->indent + (int) strlen(line) : 0, line);
dm_list_del(&row->list);
}
@@ -4560,14 +4560,14 @@ static int _json_output_array_start(struct dm_pool *mem, struct report_group_ite
}
if (item->parent->store.finished_count > 0)
- log_print("%*s", item->group->indent + (int) sizeof(JSON_SEPARATOR) - 1, JSON_SEPARATOR);
+ log_print_bypass_report("%*s", item->group->indent + (int) sizeof(JSON_SEPARATOR) - 1, JSON_SEPARATOR);
if (item->parent->parent && item->parent->data) {
- log_print("%*s", item->group->indent + (int) sizeof(JSON_OBJECT_START) - 1, JSON_OBJECT_START);
+ log_print_bypass_report("%*s", item->group->indent + (int) sizeof(JSON_OBJECT_START) - 1, JSON_OBJECT_START);
item->group->indent += JSON_INDENT_UNIT;
}
- log_print("%*s", item->group->indent + (int) strlen(output), output);
+ log_print_bypass_report("%*s", item->group->indent + (int) strlen(output), output);
item->group->indent += JSON_INDENT_UNIT;
dm_pool_free(mem, output);
@@ -4616,9 +4616,9 @@ static int _print_basic_report_header(struct dm_report *rh)
memset(underline, '=', len);
if (rh->group_item->parent->store.finished_count > 0)
- log_print("%s", "");
- log_print("%s", report_name);
- log_print("%s", underline);
+ log_print_bypass_report("%s", "");
+ log_print_bypass_report("%s", report_name);
+ log_print_bypass_report("%s", underline);
dm_pool_free(rh->mem, underline);
return 1;
@@ -4665,7 +4665,7 @@ static int _report_group_create_basic(struct dm_report_group *group)
static int _report_group_create_json(struct dm_report_group *group)
{
- log_print(JSON_OBJECT_START);
+ log_print_bypass_report(JSON_OBJECT_START);
group->indent += JSON_INDENT_UNIT;
return 1;
}
@@ -4742,7 +4742,7 @@ static int _report_group_push_single(struct report_group_item *item, void *data)
static int _report_group_push_basic(struct report_group_item *item, const char *name)
{
if (!item->report && !name && item->parent->store.finished_count > 0)
- log_print("%s", "");
+ log_print_bypass_report("%s", "");
return 1;
}
@@ -4769,8 +4769,8 @@ static int _report_group_push_json(struct report_group_item *item, const char *n
return 0;
}
if (item->parent->store.finished_count > 0)
- log_print("%*s", item->group->indent + (int) sizeof(JSON_SEPARATOR) - 1, JSON_SEPARATOR);
- log_print("%*s", item->group->indent + (int) sizeof(JSON_OBJECT_START) - 1, JSON_OBJECT_START);
+ log_print_bypass_report("%*s", item->group->indent + (int) sizeof(JSON_SEPARATOR) - 1, JSON_SEPARATOR);
+ log_print_bypass_report("%*s", item->group->indent + (int) sizeof(JSON_OBJECT_START) - 1, JSON_OBJECT_START);
item->group->indent += JSON_INDENT_UNIT;
}
@@ -4848,11 +4848,11 @@ static int _report_group_pop_json(struct report_group_item *item)
if (item->output_done && item->needs_closing) {
if (item->data) {
item->group->indent -= JSON_INDENT_UNIT;
- log_print("%*s", item->group->indent + (int) sizeof(JSON_ARRAY_END) - 1, JSON_ARRAY_END);
+ log_print_bypass_report("%*s", item->group->indent + (int) sizeof(JSON_ARRAY_END) - 1, JSON_ARRAY_END);
}
if (item->parent->data && item->parent->parent) {
item->group->indent -= JSON_INDENT_UNIT;
- log_print("%*s", item->group->indent + (int) sizeof(JSON_OBJECT_END) - 1, JSON_OBJECT_END);
+ log_print_bypass_report("%*s", item->group->indent + (int) sizeof(JSON_OBJECT_END) - 1, JSON_OBJECT_END);
}
item->needs_closing = 0;
}
@@ -4915,7 +4915,7 @@ static int _report_group_destroy_basic(void)
static int _report_group_destroy_json(void)
{
- log_print(JSON_OBJECT_END);
+ log_print_bypass_report(JSON_OBJECT_END);
return 1;
}
7 years, 11 months
master - report: add report_current_object_cmdlog fn as a shortcut for reporting current object's log item
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=fe63715f25cf15...
Commit: fe63715f25cf156b07e144a2e7b5cce56d32e39e
Parent: 7d4a15e53a19dcc073b7037638d811eba3a85edf
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon May 23 15:09:05 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
report: add report_current_object_cmdlog fn as a shortcut for reporting current object's log item
---
lib/report/report.c | 11 +++++++++++
lib/report/report.h | 1 +
2 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/lib/report/report.c b/lib/report/report.c
index eec9756..1436cfe 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -3869,3 +3869,14 @@ int report_cmdlog(void *handle, const char *type, const char *context,
return 1;
}
+
+int report_current_object_cmdlog(const char *type, const char *msg, int32_t ret_code)
+{
+ log_report_t log_state = log_get_report_state();
+
+ return report_cmdlog(log_state.report, type, log_get_report_context_name(log_state.context),
+ log_get_report_object_type_name(log_state.object_type),
+ log_state.object_name, log_state.object_id,
+ log_state.object_group, log_state.object_group_id,
+ msg, stored_errno(), ret_code);
+}
diff --git a/lib/report/report.h b/lib/report/report.h
index 37e1061..a6f17cd 100644
--- a/lib/report/report.h
+++ b/lib/report/report.h
@@ -110,6 +110,7 @@ int report_cmdlog(void *handle, const char *type, const char *context,
const char *object_id, const char *object_group,
const char *object_group_id, const char *msg,
int current_errno, int ret_code);
+int report_current_object_cmdlog(const char *type, const char *msg, int32_t ret_code);
int report_output(void *handle);
#endif
7 years, 11 months
master - log: log warnings and errors via report if set; add log_set_report* fns
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7d4a15e53a19dc...
Commit: 7d4a15e53a19dcc073b7037638d811eba3a85edf
Parent: 8cfc385491484e71d66e5991e09c3d0a47570a13
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue May 3 11:46:52 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
log: log warnings and errors via report if set; add log_set_report* fns
This patch adds structures and functions to reroute error and warning
logs to log report, if it's set.
There are 5 new functions:
- log_set_report
Set log report where logging will be rerouted.
- log_set_report_context
Set context globally so any report_cmdlog call will use it.
- log_set_report_object_type
Set object type globally so any report_cmdlog call will use it.
- log_set_report_object_name_and_id
Set object ID and name globally so any report_cmdlog call will use it.
- log_set_report_object_group_and_group_id
Set object group ID and name globally so any report_cmdlog call will use it.
These functions will be called during LVM command processing so any logs
which are rerouted to log report contain proper information about current
processing state.
---
WHATS_NEW | 1 +
lib/log/log.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++-
lib/log/lvm-logging.h | 37 ++++++++++++++++++
lib/report/report.h | 3 +-
tools/reporter.c | 8 +++-
tools/toollib.c | 8 +++-
tools/toollib.h | 1 +
7 files changed, 154 insertions(+), 5 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index edbc0f3..88e785a 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Log warnings and errors via report during cmd processing if this is enabled.
Make it possible to iterate over internal 'orphan' VGs in process_each_vg fn.
Make -S|--select option groupable that allows this option to be repeated.
Make -O|--sort option groupable that allows this option to be repeated.
diff --git a/lib/log/log.c b/lib/log/log.c
index 7b0026f..3181fdd 100644
--- a/lib/log/log.c
+++ b/lib/log/log.c
@@ -17,6 +17,7 @@
#include "device.h"
#include "memlock.h"
#include "defaults.h"
+#include "report.h"
#include <stdio.h>
#include <stdarg.h>
@@ -47,6 +48,15 @@ static size_t _lvm_errmsg_size = 0;
static size_t _lvm_errmsg_len = 0;
#define MAX_ERRMSG_LEN (512 * 1024) /* Max size of error buffer 512KB */
+static log_report_t _log_report = {
+ .report = NULL,
+ .context = LOG_REPORT_CONTEXT_NULL,
+ .object_type = LOG_REPORT_OBJECT_TYPE_NULL,
+ .object_id = NULL,
+ .object_name = NULL,
+ .object_group = NULL
+};
+
void init_log_fn(lvm2_log_fn_t log_fn)
{
_lvm2_log_fn = log_fn;
@@ -260,6 +270,38 @@ void reset_log_duplicated(void) {
}
}
+static const char *_get_log_level_name(int level)
+{
+ static const char *log_level_names[] = {"", /* unassigned */
+ "", /* unassigned */
+ "fatal", /* _LOG_FATAL */
+ "error", /* _LOG_ERROR */
+ "warn", /* _LOG_WARN */
+ "notice" /* _LOG_NOTICE */
+ "info", /* _LOG_INFO */
+ "debug" /* _LOG_DEBUG */
+ };
+ level &= ~_LOG_STDERR;
+ return log_level_names[level];
+}
+
+const char *log_get_report_context_name(log_report_context_t context)
+{
+ static const char *log_context_names[LOG_REPORT_CONTEXT_COUNT] = {[LOG_REPORT_CONTEXT_NULL] = "",
+ [LOG_REPORT_CONTEXT_PROCESSING] = "processing"};
+ return log_context_names[context];
+}
+
+
+const char *log_get_report_object_type_name(log_report_object_type_t object_type)
+{
+ static const char *log_object_type_names[LOG_REPORT_OBJECT_TYPE_COUNT] = {[LOG_REPORT_OBJECT_TYPE_NULL] = "",
+ [LOG_REPORT_OBJECT_TYPE_PV] = "pv",
+ [LOG_REPORT_OBJECT_TYPE_VG] = "vg",
+ [LOG_REPORT_OBJECT_TYPE_LV] = "lv"};
+ return log_object_type_names[object_type];
+}
+
void print_log(int level, const char *file, int line, int dm_errno_or_class,
const char *format, ...)
{
@@ -277,6 +319,8 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
static int _abort_on_internal_errors_env_present = -1;
static int _abort_on_internal_errors_env = 0;
char *env_str;
+ struct dm_report *orig_report;
+ int logged_via_report = 0;
level &= ~(_LOG_STDERR|_LOG_ONCE);
@@ -309,6 +353,7 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
if (_lvm2_log_fn ||
(_store_errmsg && (level <= _LOG_ERR)) ||
+ (_log_report.report && (use_stderr || (level <=_LOG_ERR))) ||
log_once) {
va_start(ap, format);
n = vsnprintf(message, sizeof(message), trformat, ap);
@@ -356,6 +401,23 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
}
}
+ if (_log_report.report && (use_stderr || (level <= _LOG_ERR))) {
+ orig_report = _log_report.report;
+ _log_report.report = NULL;
+
+ if (!report_cmdlog(orig_report, _get_log_level_name(level),
+ log_get_report_context_name(_log_report.context),
+ log_get_report_object_type_name(_log_report.object_type),
+ _log_report.object_name, _log_report.object_id,
+ _log_report.object_group, _log_report.object_group_id,
+ message, _lvm_errno, 0))
+ fprintf(stderr, _("failed to report cmdstatus"));
+ else
+ logged_via_report = 1;
+
+ _log_report.report = orig_report;
+ }
+
if (_lvm2_log_fn) {
_lvm2_log_fn(level, file, line, 0, message);
if (fatal_internal_error)
@@ -364,7 +426,7 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
}
log_it:
- if ((verbose_level() >= level) && !_log_suppress) {
+ if (!logged_via_report && ((verbose_level() >= level) && !_log_suppress)) {
if (verbose_level() > _LOG_DEBUG) {
(void) dm_snprintf(buf, sizeof(buf), "#%s:%d ",
file, line);
@@ -462,3 +524,40 @@ void print_log(int level, const char *file, int line, int dm_errno_or_class,
_already_logging = 0;
}
}
+
+log_report_t log_get_report_state(void)
+{
+ return _log_report;
+}
+
+void log_restore_report_state(log_report_t log_report)
+{
+ _log_report = log_report;
+}
+
+void log_set_report(struct dm_report *report)
+{
+ _log_report.report = report;
+}
+
+void log_set_report_context(log_report_context_t context)
+{
+ _log_report.context = context;
+}
+
+void log_set_report_object_type(log_report_object_type_t object_type)
+{
+ _log_report.object_type = object_type;
+}
+
+void log_set_report_object_group_and_group_id(const char *group, const char *id)
+{
+ _log_report.object_group = group;
+ _log_report.object_group_id = id;
+}
+
+void log_set_report_object_name_and_id(const char *name, const char *id)
+{
+ _log_report.object_name = name;
+ _log_report.object_id = id;
+}
diff --git a/lib/log/lvm-logging.h b/lib/log/lvm-logging.h
index 56e95ff..5789c0b 100644
--- a/lib/log/lvm-logging.h
+++ b/lib/log/lvm-logging.h
@@ -65,4 +65,41 @@ int log_suppress(int suppress);
/* Suppress messages to syslog */
void syslog_suppress(int suppress);
+/* Hooks to handle logging through report. */
+typedef enum {
+ LOG_REPORT_CONTEXT_NULL,
+ LOG_REPORT_CONTEXT_PROCESSING,
+ LOG_REPORT_CONTEXT_COUNT
+} log_report_context_t;
+
+typedef enum {
+ LOG_REPORT_OBJECT_TYPE_NULL,
+ LOG_REPORT_OBJECT_TYPE_PV,
+ LOG_REPORT_OBJECT_TYPE_VG,
+ LOG_REPORT_OBJECT_TYPE_LV,
+ LOG_REPORT_OBJECT_TYPE_COUNT
+} log_report_object_type_t;
+
+typedef struct log_report {
+ struct dm_report *report;
+ log_report_context_t context;
+ log_report_object_type_t object_type;
+ const char *object_name;
+ const char *object_id;
+ const char *object_group;
+ const char *object_group_id;
+} log_report_t;
+
+log_report_t log_get_report_state(void);
+void log_restore_report_state(log_report_t log_report);
+
+void log_set_report(struct dm_report *report);
+void log_set_report_context(log_report_context_t context);
+void log_set_report_object_type(log_report_object_type_t object_type);
+void log_set_report_object_group_and_group_id(const char *group, const char *group_id);
+void log_set_report_object_name_and_id(const char *name, const char *id);
+
+const char *log_get_report_context_name(log_report_context_t context);
+const char *log_get_report_object_type_name(log_report_object_type_t object_type);
+
#endif
diff --git a/lib/report/report.h b/lib/report/report.h
index f5df51e..37e1061 100644
--- a/lib/report/report.h
+++ b/lib/report/report.h
@@ -82,7 +82,8 @@ typedef int (*field_report_fn) (struct report_handle * dh, struct field * field,
const void *data);
int report_format_init(struct cmd_context *cmd, dm_report_group_type_t *report_group_type,
- struct dm_report_group **report_group, struct dm_report **log_rh);
+ struct dm_report_group **report_group, struct dm_report **log_rh,
+ log_report_t *saved_log_report_state);
void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
report_type_t *report_type, const char *separator,
diff --git a/tools/reporter.c b/tools/reporter.c
index 0509c88..d376947 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -1418,7 +1418,8 @@ int devtypes(struct cmd_context *cmd, int argc, char **argv)
#define REPORT_FORMAT_NAME_JSON "json"
int report_format_init(struct cmd_context *cmd, dm_report_group_type_t *report_group_type,
- struct dm_report_group **report_group, struct dm_report **log_rh)
+ struct dm_report_group **report_group, struct dm_report **log_rh,
+ log_report_t *saved_log_report_state)
{
int config_set = find_config_tree_node(cmd, report_output_format_CFG, NULL) != NULL;
const char *config_format_str = find_config_tree_str(cmd, report_output_format_CFG, NULL);
@@ -1483,6 +1484,11 @@ int report_format_init(struct cmd_context *cmd, dm_report_group_type_t *report_g
*report_group = new_report_group;
if (tmp_log_rh)
*log_rh = tmp_log_rh;
+
+ if (saved_log_report_state) {
+ *saved_log_report_state = log_get_report_state();
+ log_set_report(*log_rh);
+ }
return 1;
bad:
if (!dm_report_group_destroy(new_report_group))
diff --git a/tools/toollib.c b/tools/toollib.c
index 925157d..fe162d1 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1729,11 +1729,12 @@ struct processing_handle *init_processing_handle(struct cmd_context *cmd, struct
if (!parent_handle) {
if (!report_format_init(cmd, &handle->report_group_type, &handle->report_group,
- &handle->log_rh)) {
+ &handle->log_rh, &handle->saved_log_report_state)) {
dm_pool_free(cmd->mem, handle);
return NULL;
}
- }
+ } else
+ handle->saved_log_report_state = log_get_report_state();
return handle;
}
@@ -1767,6 +1768,9 @@ void destroy_processing_handle(struct cmd_context *cmd, struct processing_handle
if (handle) {
if (handle->selection_handle && handle->selection_handle->selection_rh)
dm_report_free(handle->selection_handle->selection_rh);
+
+ log_restore_report_state(handle->saved_log_report_state);
+
if (!dm_report_group_destroy(handle->report_group))
stack;
if (handle->log_rh)
diff --git a/tools/toollib.h b/tools/toollib.h
index 179efe5..1144793 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -76,6 +76,7 @@ struct processing_handle {
dm_report_group_type_t report_group_type;
struct dm_report_group *report_group;
struct dm_report *log_rh;
+ log_report_t saved_log_report_state;
void *custom_handle;
};
7 years, 11 months
master - toollib: make it possible to also process internal VGs, add 'include_internal' switch to process_each_vg fn
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8cfc385491484e...
Commit: 8cfc385491484e71d66e5991e09c3d0a47570a13
Parent: 31aaa3be71597ec53262177bea76365605e9199f
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue May 3 11:46:28 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
toollib: make it possible to also process internal VGs, add 'include_internal' switch to process_each_vg fn
The lvm fullreport works per VG and as such, the vg, lv, pv, seg and
pvseg subreport is done for each VG. However, if the PV is not part of
any VG yet, we still want to display pv and pvseg subreports for these
"orphan" PVs - so enable this for lvm fullreport's process_each_vg call.
---
WHATS_NEW | 1 +
tools/lvcreate.c | 2 +-
tools/lvrename.c | 2 +-
tools/lvresize.c | 2 +-
tools/polldaemon.c | 4 ++--
tools/pvscan.c | 2 +-
tools/reporter.c | 10 +++++-----
tools/toollib.c | 6 ++++--
tools/toollib.h | 1 +
tools/vgcfgbackup.c | 2 +-
tools/vgchange.c | 2 +-
tools/vgck.c | 2 +-
tools/vgconvert.c | 2 +-
tools/vgdisplay.c | 2 +-
tools/vgexport.c | 2 +-
tools/vgextend.c | 2 +-
tools/vgimport.c | 2 +-
tools/vgreduce.c | 2 +-
tools/vgremove.c | 2 +-
tools/vgrename.c | 2 +-
tools/vgscan.c | 2 +-
21 files changed, 29 insertions(+), 25 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 01d6bbc..edbc0f3 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Make it possible to iterate over internal 'orphan' VGs in process_each_vg fn.
Make -S|--select option groupable that allows this option to be repeated.
Make -O|--sort option groupable that allows this option to be repeated.
Add --configreport option to select report for which next options are applied.
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index fb28dc5..88518d2 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -1564,7 +1564,7 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &pp;
- ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, handle,
+ ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, 0, handle,
&_lvcreate_single);
_destroy_lvcreate_params(&lp);
diff --git a/tools/lvrename.c b/tools/lvrename.c
index 4dfcda2..74248ee 100644
--- a/tools/lvrename.c
+++ b/tools/lvrename.c
@@ -217,7 +217,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &lp;
- ret = process_each_vg(cmd, 0, NULL, vg_name, NULL, READ_FOR_UPDATE, handle,
+ ret = process_each_vg(cmd, 0, NULL, vg_name, NULL, READ_FOR_UPDATE, 0, handle,
_lvrename_single);
destroy_processing_handle(cmd, handle);
diff --git a/tools/lvresize.c b/tools/lvresize.c
index 05e386f..38ad98f 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -223,7 +223,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &lp;
- ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, handle,
+ ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, 0, handle,
&_lvresize_single);
destroy_processing_handle(cmd, handle);
diff --git a/tools/polldaemon.c b/tools/polldaemon.c
index e12a694..2b64c4e 100644
--- a/tools/polldaemon.c
+++ b/tools/polldaemon.c
@@ -364,7 +364,7 @@ static void _poll_for_all_vgs(struct cmd_context *cmd,
while (1) {
parms->outstanding_count = 0;
- process_each_vg(cmd, 0, NULL, NULL, NULL, READ_FOR_UPDATE, handle, _poll_vg);
+ process_each_vg(cmd, 0, NULL, NULL, NULL, READ_FOR_UPDATE, 0, handle, _poll_vg);
if (!parms->outstanding_count)
break;
if (parms->interval)
@@ -508,7 +508,7 @@ static void _lvmpolld_poll_for_all_vgs(struct cmd_context *cmd,
handle->custom_handle = &lpdp;
- process_each_vg(cmd, 0, NULL, NULL, NULL, 0, handle, _lvmpolld_init_poll_vg);
+ process_each_vg(cmd, 0, NULL, NULL, NULL, 0, 0, handle, _lvmpolld_init_poll_vg);
first = dm_list_first(&lpdp.idls);
diff --git a/tools/pvscan.c b/tools/pvscan.c
index db678d1..a1f5ef3 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -287,7 +287,7 @@ static int _pvscan_autoactivate(struct cmd_context *cmd, struct pvscan_aa_params
dev_cache_full_scan(cmd->full_filter);
- ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, 0, handle, _pvscan_autoactivate_single);
+ ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, 0, 0, handle, _pvscan_autoactivate_single);
destroy_processing_handle(cmd, handle);
diff --git a/tools/reporter.c b/tools/reporter.c
index 1fcb338..0509c88 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -1084,8 +1084,8 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
if (args->full_report_vg)
r = _report_all_in_vg(cmd, handle, args->full_report_vg, VGS, lv_info_needed, lv_segment_status_needed);
else
- r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL, 0,
- handle, &_vgs_single);
+ r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
+ 0, 0, handle, &_vgs_single);
break;
case LABEL:
r = process_each_label(cmd, args->argc, args->argv,
@@ -1101,7 +1101,7 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
handle, &_pvs_single);
else
r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
- 0, handle, &_pvs_in_vg);
+ 0, 0, handle, &_pvs_in_vg);
}
break;
case SEGS:
@@ -1128,7 +1128,7 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
&_pvsegs_single);
else
r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
- 0, handle, &_pvsegs_in_vg);
+ 0, 0, handle, &_pvsegs_in_vg);
}
break;
case FULL:
@@ -1367,7 +1367,7 @@ static int _report(struct cmd_context *cmd, int argc, char **argv, report_type_t
if (single_args->report_type == FULL) {
handle->custom_handle = &args;
- r = process_each_vg(cmd, argc, argv, NULL, NULL, 0, handle, &_full_report_single);
+ r = process_each_vg(cmd, argc, argv, NULL, NULL, 0, 1, handle, &_full_report_single);
} else
r = _do_report(cmd, handle, &args, single_args);
diff --git a/tools/toollib.c b/tools/toollib.c
index e67e47a..925157d 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1875,7 +1875,8 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
skip = 0;
notfound = 0;
- if (vg_uuid && !id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid)))
+ if (vg_uuid && !is_orphan_vg(vg_name) &&
+ !id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid)))
stack;
log_very_verbose("Processing VG %s %s", vg_name, vg_uuid ? uuid : "");
@@ -2091,6 +2092,7 @@ int process_each_vg(struct cmd_context *cmd,
const char *one_vgname,
struct dm_list *use_vgnames,
uint32_t read_flags,
+ int include_internal,
struct processing_handle *handle,
process_single_vg_fn_t process_single_vg)
{
@@ -2158,7 +2160,7 @@ int process_each_vg(struct cmd_context *cmd,
*/
log_debug("Get list of VGs on system");
- if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0)) {
+ if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, include_internal)) {
ret_max = ECMD_FAILED;
goto_out;
}
diff --git a/tools/toollib.h b/tools/toollib.h
index 8cd9087..179efe5 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -106,6 +106,7 @@ int process_each_vg(struct cmd_context *cmd,
const char *one_vgname,
struct dm_list *use_vgnames,
uint32_t flags,
+ int include_internal,
struct processing_handle *handle,
process_single_vg_fn_t process_single_vg);
diff --git a/tools/vgcfgbackup.c b/tools/vgcfgbackup.c
index c47c1ef..34fe08f 100644
--- a/tools/vgcfgbackup.c
+++ b/tools/vgcfgbackup.c
@@ -94,7 +94,7 @@ int vgcfgbackup(struct cmd_context *cmd, int argc, char **argv)
init_pvmove(1);
- ret = process_each_vg(cmd, argc, argv, NULL, NULL, READ_ALLOW_INCONSISTENT,
+ ret = process_each_vg(cmd, argc, argv, NULL, NULL, READ_ALLOW_INCONSISTENT, 0,
handle, &vg_backup_single);
dm_free(last_filename);
diff --git a/tools/vgchange.c b/tools/vgchange.c
index bbd9e1f..4f6d847 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -1216,7 +1216,7 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, lockstart_ARG) || arg_is_set(cmd, lockstop_ARG))
flags |= READ_ALLOW_EXPORTED;
- ret = process_each_vg(cmd, argc, argv, NULL, NULL, flags, NULL, &vgchange_single);
+ ret = process_each_vg(cmd, argc, argv, NULL, NULL, flags, 0, NULL, &vgchange_single);
/* Wait for lock-start ops that were initiated in vgchange_lockstart. */
diff --git a/tools/vgck.c b/tools/vgck.c
index 27a1d00..54bc9d6 100644
--- a/tools/vgck.c
+++ b/tools/vgck.c
@@ -38,6 +38,6 @@ static int vgck_single(struct cmd_context *cmd __attribute__((unused)),
int vgck(struct cmd_context *cmd, int argc, char **argv)
{
lvmetad_make_unused(cmd);
- return process_each_vg(cmd, argc, argv, NULL, NULL, 0, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, 0, 0, NULL,
&vgck_single);
}
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index 6ae675f..846db05 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -181,6 +181,6 @@ int vgconvert(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, 0, NULL,
&vgconvert_single);
}
diff --git a/tools/vgdisplay.c b/tools/vgdisplay.c
index c805e68..e9482df 100644
--- a/tools/vgdisplay.c
+++ b/tools/vgdisplay.c
@@ -89,7 +89,7 @@ int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
}
**********/
- return process_each_vg(cmd, argc, argv, NULL, NULL, 0, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, 0, 0, NULL,
vgdisplay_single);
/******** FIXME Need to count number processed
diff --git a/tools/vgexport.c b/tools/vgexport.c
index afe9a14..592e145 100644
--- a/tools/vgexport.c
+++ b/tools/vgexport.c
@@ -80,6 +80,6 @@ int vgexport(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, 0, NULL,
&vgexport_single);
}
diff --git a/tools/vgextend.c b/tools/vgextend.c
index 8f44672..1c3743b 100644
--- a/tools/vgextend.c
+++ b/tools/vgextend.c
@@ -198,7 +198,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &vp;
ret = process_each_vg(cmd, 0, NULL, vg_name, NULL,
- READ_FOR_UPDATE, handle,
+ READ_FOR_UPDATE, 0, handle,
restoremissing ? &_vgextend_restoremissing : &_vgextend_single);
destroy_processing_handle(cmd, handle);
diff --git a/tools/vgimport.c b/tools/vgimport.c
index 1f2e14d..07a889b 100644
--- a/tools/vgimport.c
+++ b/tools/vgimport.c
@@ -109,6 +109,6 @@ int vgimport(struct cmd_context *cmd, int argc, char **argv)
return process_each_vg(cmd, argc, argv, NULL, NULL,
READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
- NULL,
+ 0, NULL,
&vgimport_single);
}
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index ae86a67..bae2b3e 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -247,7 +247,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
process_each_vg(cmd, 0, NULL, vg_name, NULL,
READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
- handle, &_vgreduce_repair_single);
+ 0, handle, &_vgreduce_repair_single);
if (vp.already_consistent) {
log_print_unless_silent("Volume group \"%s\" is already consistent", vg_name);
diff --git a/tools/vgremove.c b/tools/vgremove.c
index 1d1a40f..f0da2f8 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -110,7 +110,7 @@ int vgremove(struct cmd_context *cmd, int argc, char **argv)
cmd->handles_missing_pvs = 1;
ret = process_each_vg(cmd, argc, argv, NULL, NULL,
- READ_FOR_UPDATE,
+ READ_FOR_UPDATE, 0,
NULL, &vgremove_single);
return ret;
diff --git a/tools/vgrename.c b/tools/vgrename.c
index 3dceeab..2006193 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -246,7 +246,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
ret = process_each_vg(cmd, 0, NULL, vg_name_old, NULL,
READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
- handle, _vgrename_single);
+ 0, handle, _vgrename_single);
/* Needed if process_each_vg returns error before calling _single. */
if (vp.unlock_new_name)
diff --git a/tools/vgscan.c b/tools/vgscan.c
index 688e361..45a2d7e 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -117,7 +117,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
else
log_print_unless_silent("Reading volume groups from cache.");
- maxret = process_each_vg(cmd, argc, argv, NULL, NULL, 0, NULL,
+ maxret = process_each_vg(cmd, argc, argv, NULL, NULL, 0, NULL, 0,
&vgscan_single);
if (arg_count(cmd, mknodes_ARG)) {
7 years, 11 months
master - report: check report type and options used for full report's subreports
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=31aaa3be71597e...
Commit: 31aaa3be71597ec53262177bea76365605e9199f
Parent: b864a062217cf31d86343f37ecbefeeeb15610cf
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Tue May 3 11:42:55 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
report: check report type and options used for full report's subreports
If we have fullreport, make sure that the options/sort keys used for
each report doesn't change its type - we want to preserve the original
type so it's always 5 different subreports within fullreport (vg, lv, pv,
seg, pvseg). Since we have all report types within fullreport, users
should add fields under proper subreport type - this minimizes
duplication of info displayed on output.
---
tools/reporter.c | 36 ++++++++++++++++++++++++------------
1 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/tools/reporter.c b/tools/reporter.c
index 9dd302a..1fcb338 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -439,7 +439,8 @@ static int _pvsegs_in_vg(struct cmd_context *cmd, const char *vg_name,
return process_each_pv_in_vg(cmd, vg, handle, &_pvsegs_single);
}
-static int _get_final_report_type(int args_are_pvs,
+static int _get_final_report_type(struct report_args *args,
+ struct single_report_args *single_args,
report_type_t report_type,
int *lv_info_needed,
int *lv_segment_status_needed,
@@ -457,8 +458,11 @@ static int _get_final_report_type(int args_are_pvs,
if (report_type & PVSEGS)
report_type |= PVS;
if ((report_type & (LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS)) &&
- (report_type & (PVS | LABEL)) && !args_are_pvs) {
- log_error("Can't report LV and PV fields at the same time");
+ (report_type & (PVS | LABEL)) && !(single_args->args_are_pvs || (args->full_report_vg && single_args->report_type == PVSEGS))) {
+ log_error("Can't report LV and PV fields at the same time in %sreport type \"%s\"%s%s.",
+ args->full_report_vg ? "sub" : "" , single_args->report_prefix,
+ args->full_report_vg ? " in VG " : "",
+ args->full_report_vg ? args->full_report_vg->name: "");
return 0;
}
@@ -476,6 +480,13 @@ static int _get_final_report_type(int args_are_pvs,
else if (report_type & (LVS | LVSINFO | LVSSTATUS | LVSINFOSTATUS))
report_type = LVS;
+ if (args->full_report_vg && (report_type != single_args->report_type)) {
+ /* FIXME: Tell user about which columns exactly are incorrectly used for that report type... */
+ log_error("Subreport of type \"%s\" for VG %s contains columns which lead to change of report type. "
+ "Add these columns to proper subreport type.", single_args->report_prefix, args->full_report_vg->name);
+ return 0;
+ }
+
*final_report_type = report_type;
return 1;
}
@@ -579,15 +590,18 @@ int report_for_selection(struct cmd_context *cmd,
struct logical_volume *lv)
{
struct selection_handle *sh = parent_handle->selection_handle;
- int args_are_pvs = sh->orig_report_type == PVS;
+ struct report_args args = {0};
+ struct single_report_args *single_args = &args.single_args[REPORT_IDX_SINGLE];
int do_lv_info, do_lv_seg_status;
struct processing_handle *handle;
int r = 0;
- if (!_get_final_report_type(args_are_pvs,
- sh->orig_report_type | sh->report_type,
- &do_lv_info,
- &do_lv_seg_status,
+ single_args->report_type = sh->orig_report_type | sh->report_type;
+ single_args->args_are_pvs = sh->orig_report_type == PVS;
+
+ if (!_get_final_report_type(&args, single_args,
+ single_args->report_type,
+ &do_lv_info, &do_lv_seg_status,
&sh->report_type))
return_0;
@@ -1023,10 +1037,8 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
handle->custom_handle = report_handle;
- if (!_get_final_report_type(single_args->args_are_pvs,
- report_type, &lv_info_needed,
- &lv_segment_status_needed,
- &report_type))
+ if (!_get_final_report_type(args, single_args, report_type, &lv_info_needed,
+ &lv_segment_status_needed, &report_type))
goto_out;
if (handle->report_group) {
7 years, 11 months
master - report: recognize selection (-S|--select) for each subreport; make -S|--select groupable
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b864a062217cf3...
Commit: b864a062217cf31d86343f37ecbefeeeb15610cf
Parent: e081203f3e2ee5e3270c7f5f2753ed446d8b72cb
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Thu May 26 15:20:27 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Mon Jun 20 11:33:42 2016 +0200
report: recognize selection (-S|--select) for each subreport; make -S|--select groupable
---
WHATS_NEW | 1 +
lib/report/report.h | 1 +
tools/args.h | 2 +-
tools/reporter.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++----
tools/toollib.c | 7 ++++-
5 files changed, 57 insertions(+), 8 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index fb5d3e7..01d6bbc 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.158 -
=================================
+ Make -S|--select option groupable that allows this option to be repeated.
Make -O|--sort option groupable that allows this option to be repeated.
Add --configreport option to select report for which next options are applied.
Add support for priorities on grouping command arguments.
diff --git a/lib/report/report.h b/lib/report/report.h
index 20ccd99..f5df51e 100644
--- a/lib/report/report.h
+++ b/lib/report/report.h
@@ -88,6 +88,7 @@ void *report_init(struct cmd_context *cmd, const char *format, const char *keys,
report_type_t *report_type, const char *separator,
int aligned, int buffered, int headings, int field_prefixes,
int quoted, int columns_as_rows, const char *selection);
+int report_get_single_selection(struct cmd_context *cmd, const char **selection);
void *report_init_for_selection(struct cmd_context *cmd, report_type_t *report_type,
const char *selection);
const char *report_get_field_prefix(report_type_t report_type);
diff --git a/tools/args.h b/tools/args.h
index 985f5d1..b7b2262 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -206,7 +206,7 @@ arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg, 0, 0)
arg(snapshot_ARG, 's', "snapshot", NULL, 0, 0)
arg(short_ARG, 's', "short", NULL, 0, 0)
arg(stdin_ARG, 's', "stdin", NULL, 0, 0)
-arg(select_ARG, 'S', "select", string_arg, 0, 0)
+arg(select_ARG, 'S', "select", string_arg, ARG_GROUPABLE, 0)
arg(test_ARG, 't', "test", NULL, 0, 0)
arg(thin_ARG, 'T', "thin", NULL, 0, 0)
arg(uuid_ARG, 'u', "uuid", NULL, 0, 0)
diff --git a/tools/reporter.c b/tools/reporter.c
index 8165288..9dd302a 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -915,16 +915,60 @@ out:
return r;
}
+static int _do_report_get_selection(struct cmd_context *cmd,
+ struct report_args *args,
+ struct single_report_args *single_args,
+ report_idx_t expected_idxs[],
+ const char **ret_selection)
+{
+ struct arg_value_group_list *current_group;
+ const char *final_selection = "", *selection = NULL;
+ const char *report_name = NULL;
+ report_idx_t idx = REPORT_IDX_SINGLE;
+ int i;
+
+ dm_list_iterate_items(current_group, &cmd->arg_value_groups) {
+ if (!grouped_arg_is_set(current_group->arg_values, select_ARG))
+ continue;
+
+ if (grouped_arg_is_set(current_group->arg_values, configreport_ARG)) {
+ report_name = grouped_arg_str_value(current_group->arg_values, configreport_ARG, NULL);
+ if ((idx = _get_report_idx_from_name(single_args->report_type, report_name)) == REPORT_IDX_NULL)
+ return_0;
+ }
+
+ selection = grouped_arg_str_value(current_group->arg_values, select_ARG, NULL);
+
+ if (single_args) {
+ if (!_should_process_report_idx(single_args->report_type, idx))
+ continue;
+ args->single_args[idx].selection = selection;
+ final_selection = selection;
+ } else {
+ for (i = 0; expected_idxs[i] != REPORT_IDX_NULL; i++) {
+ if (idx == expected_idxs[i])
+ final_selection = selection;
+ }
+ }
+ }
+
+ if (ret_selection)
+ *ret_selection = final_selection;
+
+ return 1;
+}
+
static int _get_report_selection(struct cmd_context *cmd,
struct report_args *args,
struct single_report_args *single_args)
{
- int r = ECMD_PROCESSED;
-
- if (arg_count(cmd, select_ARG))
- single_args->selection = arg_str_value(cmd, select_ARG, NULL);
+ return _do_report_get_selection(cmd, args, single_args, NULL, NULL) ? ECMD_PROCESSED : ECMD_FAILED;
+}
- return r;
+int report_get_single_selection(struct cmd_context *cmd, const char **selection)
+{
+ report_idx_t expected_idxs[] = {REPORT_IDX_SINGLE, REPORT_IDX_NULL};
+ return _do_report_get_selection(cmd, NULL, NULL, expected_idxs, selection);
}
static int _set_report_prefix_and_name(struct single_report_args *single_args)
diff --git a/tools/toollib.c b/tools/toollib.c
index 3b2ad6a..e67e47a 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1742,15 +1742,18 @@ int init_selection_handle(struct cmd_context *cmd, struct processing_handle *han
report_type_t initial_report_type)
{
struct selection_handle *sh;
+ const char *selection;
if (!(sh = dm_pool_zalloc(cmd->mem, sizeof(struct selection_handle)))) {
log_error("_init_selection_handle: failed to allocate memory for selection handle");
return 0;
}
+ if (!report_get_single_selection(cmd, &selection))
+ return_0;
+
sh->report_type = initial_report_type;
- if (!(sh->selection_rh = report_init_for_selection(cmd, &sh->report_type,
- arg_str_value(cmd, select_ARG, NULL)))) {
+ if (!(sh->selection_rh = report_init_for_selection(cmd, &sh->report_type, selection))) {
dm_pool_free(cmd->mem, sh);
return_0;
}
7 years, 11 months