diff options
author | Peter Rajnoha <prajnoha@redhat.com> | 2015-05-08 10:24:31 +0200 |
---|---|---|
committer | Peter Rajnoha <prajnoha@redhat.com> | 2015-05-08 10:24:31 +0200 |
commit | 7d54fc64e763c07f2f75dab8ca1281aea475cf5d (patch) | |
tree | 592a58b199007f9e84f1021b7ed08c41180ce8ff | |
parent | 73bcbb5b7c31885f39b273b8f883992acb296598 (diff) | |
download | lvm2-dev-prajnoha-select-time.tar.gz |
report: select: initial code for time supportdev-prajnoha-select-time
-rw-r--r-- | lib/properties/prop_common.h | 3 | ||||
-rw-r--r-- | lib/report/report.c | 1 | ||||
-rw-r--r-- | libdm/libdevmapper.h | 1 | ||||
-rw-r--r-- | libdm/libdm-report.c | 145 |
4 files changed, 123 insertions, 27 deletions
diff --git a/lib/properties/prop_common.h b/lib/properties/prop_common.h index 9cc963aba..19b8f7052 100644 --- a/lib/properties/prop_common.h +++ b/lib/properties/prop_common.h @@ -127,8 +127,9 @@ static int _ ## NAME ## _get (const void *obj, struct lvm_property_type *prop) \ #define BIN 3 #define SIZ 4 #define PCT 5 -#define STR_LIST 6 +#define TIM 6 #define SNUM 7 /* Signed Number */ +#define STR_LIST 8 #define FIELD_MODIFIABLE 0x00000001 #define FIELD(type, strct, field_type, head, field, width, fn, id, desc, settable) \ diff --git a/lib/report/report.c b/lib/report/report.c index bd3f51a94..641904e9f 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -2125,6 +2125,7 @@ static const struct dm_report_object_type _devtypes_report_types[] = { #define BIN DM_REPORT_FIELD_TYPE_NUMBER #define SIZ DM_REPORT_FIELD_TYPE_SIZE #define PCT DM_REPORT_FIELD_TYPE_PERCENT +#define TIM DM_REPORT_FIELD_TYPE_TIME #define STR_LIST DM_REPORT_FIELD_TYPE_STRING_LIST #define SNUM DM_REPORT_FIELD_TYPE_NUMBER #define FIELD(type, strct, sorttype, head, field, width, func, id, desc, writeable) \ diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h index 309e63fd1..7d14104c3 100644 --- a/libdm/libdevmapper.h +++ b/libdm/libdevmapper.h @@ -1675,6 +1675,7 @@ struct dm_report_field; #define DM_REPORT_FIELD_TYPE_SIZE 0x00000040 #define DM_REPORT_FIELD_TYPE_PERCENT 0x00000080 #define DM_REPORT_FIELD_TYPE_STRING_LIST 0x00000100 +#define DM_REPORT_FIELD_TYPE_TIME 0x00000200 #define DM_REPORT_FIELD_TYPE_ID_LEN 32 #define DM_REPORT_FIELD_TYPE_HEADING_LEN 32 diff --git a/libdm/libdm-report.c b/libdm/libdm-report.c index 2fe930058..c99a75ddb 100644 --- a/libdm/libdm-report.c +++ b/libdm/libdm-report.c @@ -100,11 +100,13 @@ struct op_def { #define FLD_CMP_LT 0x01000000 #define FLD_CMP_REGEX 0x02000000 #define FLD_CMP_NUMBER 0x04000000 +#define FLD_CMP_TIME 0x08000000 /* - * #define FLD_CMP_STRING 0x08000000 - * We could defined FLD_CMP_STRING here for completeness here, + * #define FLD_CMP_STRING 0x10000000 + * We could define FLD_CMP_STRING here for completeness here, * but it's not needed - we can check operator compatibility with - * field type by using FLD_CMP_REGEX and FLD_CMP_NUMBER flags only. + * field type by using FLD_CMP_REGEX, FLD_CMP_NUMBER and + * FLD_CMP_TIME flags only. */ /* @@ -115,12 +117,16 @@ struct op_def { static struct op_def _op_cmp[] = { { "=~", FLD_CMP_REGEX, "Matching regular expression. [regex]" }, { "!~", FLD_CMP_REGEX|FLD_CMP_NOT, "Not matching regular expression. [regex]" }, - { "=", FLD_CMP_EQUAL, "Equal to. [number, size, percent, string, string list]" }, - { "!=", FLD_CMP_NOT|FLD_CMP_EQUAL, "Not equal to. [number, size, percent, string, string_list]" }, - { ">=", FLD_CMP_NUMBER|FLD_CMP_GT|FLD_CMP_EQUAL, "Greater than or equal to. [number, size, percent]" }, - { ">", FLD_CMP_NUMBER|FLD_CMP_GT, "Greater than. [number, size, percent]" }, - { "<=", FLD_CMP_NUMBER|FLD_CMP_LT|FLD_CMP_EQUAL, "Less than or equal to. [number, size, percent]" }, - { "<", FLD_CMP_NUMBER|FLD_CMP_LT, "Less than. [number, size, percent]" }, + { "=", FLD_CMP_EQUAL, "Equal to. [number, size, percent, string, string list, time]" }, + { "!=", FLD_CMP_NOT|FLD_CMP_EQUAL, "Not equal to. [number, size, percent, string, string_list, time]" }, + { ">=", FLD_CMP_NUMBER|FLD_CMP_TIME|FLD_CMP_GT|FLD_CMP_EQUAL, "Greater than or equal to. [number, size, percent, time]" }, + { ">", FLD_CMP_NUMBER|FLD_CMP_TIME|FLD_CMP_GT, "Greater than. [number, size, percent, time]" }, + { "<=", FLD_CMP_NUMBER|FLD_CMP_TIME|FLD_CMP_LT|FLD_CMP_EQUAL, "Less than or equal to. [number, size, percent, time]" }, + { "<", FLD_CMP_NUMBER|FLD_CMP_TIME|FLD_CMP_LT, "Less than. [number, size, percent, time]" }, + { "since", FLD_CMP_TIME|FLD_CMP_GT|FLD_CMP_EQUAL, "Since specified time (same as '>='). [time]" }, + { "after", FLD_CMP_TIME|FLD_CMP_GT, "After specific time (same as '>'). [time]"}, + { "until", FLD_CMP_TIME|FLD_CMP_LT|FLD_CMP_EQUAL, "Until specified time (same as '<='). [time]"}, + { "before", FLD_CMP_TIME|FLD_CMP_LT, "Before specified time (same as '<'). [time]"}, { NULL, 0, NULL } }; @@ -168,6 +174,7 @@ struct field_selection { union { const char *s; uint64_t i; + time_t t; double d; struct dm_regex *r; struct selection_str_list *l; @@ -651,6 +658,7 @@ static const char *_get_field_type_name(unsigned field_type) case DM_REPORT_FIELD_TYPE_NUMBER: return "number"; case DM_REPORT_FIELD_TYPE_SIZE: return "size"; case DM_REPORT_FIELD_TYPE_PERCENT: return "percent"; + case DM_REPORT_FIELD_TYPE_TIME: return "time"; case DM_REPORT_FIELD_TYPE_STRING_LIST: return "string list"; default: return "unknown"; } @@ -1284,6 +1292,9 @@ static int _do_check_value_is_reserved(unsigned type, const void *reserved_value case DM_REPORT_FIELD_TYPE_STRING_LIST: /* FIXME Add comparison for string list */ break; + case DM_REPORT_FIELD_TYPE_TIME: + /* FIXME Add comparison for time */ + break; } return 0; @@ -1379,6 +1390,31 @@ static int _cmp_field_string(struct dm_report *rh __attribute__((unused)), return 0; } +static int _cmp_field_time(struct dm_report *rh, + uint32_t field_num, const char *field_id, + time_t a, time_t b, uint32_t flags) +{ + switch(flags & FLD_CMP_MASK) { + case FLD_CMP_EQUAL: + return a == b; + case FLD_CMP_NOT|FLD_CMP_EQUAL: + return a != b; + case FLD_CMP_TIME|FLD_CMP_GT: + return _check_value_is_reserved(rh, field_num, DM_REPORT_FIELD_TYPE_TIME, &a, &b) ? 0 : a > b; + case FLD_CMP_TIME|FLD_CMP_GT|FLD_CMP_EQUAL: + return _check_value_is_reserved(rh, field_num, DM_REPORT_FIELD_TYPE_TIME, &a, &b) ? 0 : a >= b; + case FLD_CMP_TIME|FLD_CMP_LT: + return _check_value_is_reserved(rh, field_num, DM_REPORT_FIELD_TYPE_TIME, &a, &b) ? 0 : a < b; + case FLD_CMP_TIME|FLD_CMP_LT|FLD_CMP_EQUAL: + return _check_value_is_reserved(rh, field_num, DM_REPORT_FIELD_TYPE_TIME, &a, &b) ? 0 : a <= b; + default: + log_error(INTERNAL_ERROR "_cmp_field_time: unsupported time " + "comparison type for field %s", field_id); + } + + return 0; +} + /* Matches if all items from selection string list match list value strictly 1:1. */ static int _cmp_field_string_list_strict_all(const struct str_list_sort_value *val, const struct selection_str_list *sel) @@ -1539,6 +1575,9 @@ static int _compare_selection_field(struct dm_report *rh, r = _cmp_field_string_list(rh, f->props->field_num, field_id, (const struct str_list_sort_value *) f->sort_value, fs->v.l, fs->flags); break; + case DM_REPORT_FIELD_TYPE_TIME: + r = _cmp_field_time(rh, f->props->field_num, field_id, *(const time_t *) f->sort_value, fs->v.t, fs->flags); + break; default: log_error(INTERNAL_ERROR "_compare_selection_field: unknown field type for field %s", field_id); } @@ -2293,6 +2332,12 @@ bad: return s; } +static const char *_tok_value_time(const char *s, const char **begin, + const char **end, time_t *time) +{ + return s; +} + /* * Input: * ft - field type for which the value is parsed @@ -2317,6 +2362,7 @@ static const char *_tok_value(struct dm_report *rh, int expected_type = ft->flags & DM_REPORT_FIELD_TYPE_MASK; struct selection_str_list **str_list; uint64_t *factor; + time_t *time; const char *tmp; char c; @@ -2395,6 +2441,28 @@ static const char *_tok_value(struct dm_report *rh, } *flags |= expected_type; + /* + * FLD_CMP_NUMBER shares operators with FLD_CMP_TIME, + * but we have NUMBER here, so remove FLD_CMP_TIME. + */ + *flags &= ~FLD_CMP_TIME; + break; + + case DM_REPORT_FIELD_TYPE_TIME: + time = (time_t *) custom; + if (!(s = _tok_value_time(s, begin, end, time))) { + log_error("Failed to parse time value " + "for selection field %s.", ft->id); + return NULL; + } + + *flags |= DM_REPORT_FIELD_TYPE_TIME; + /* + * FLD_CMP_TIME shares operators with FLD_CMP_NUMBER, + * but we have TIME here, so remove FLD_CMP_NUMBER. + */ + *flags &= ~FLD_CMP_NUMBER; + break; } return s; @@ -2501,7 +2569,7 @@ static struct field_selection *_create_field_selection(struct dm_report *rh, goto error; } } else { - /* STRING, NUMBER, SIZE or STRING_LIST */ + /* STRING, NUMBER, SIZE, PERCENT, STRING_LIST, TIME */ if (!(s = dm_pool_alloc(rh->selection->mem, len + 1))) { log_error("dm_report: dm_pool_alloc failed to store " "value for selection field %s", field_id); @@ -2583,6 +2651,13 @@ static struct field_selection *_create_field_selection(struct dm_report *rh, goto error; } break; + case DM_REPORT_FIELD_TYPE_TIME: + fs->v.t = *((time_t *)custom); + if (_check_value_is_reserved(rh, field_num, DM_REPORT_FIELD_TYPE_TIME, &fs->v.t, NULL)) { + log_error("Time value found in selection is reserved."); + goto error; + } + break; default: log_error(INTERNAL_ERROR "_create_field_selection: " "unknown type of selection field %s", field_id); @@ -2674,7 +2749,7 @@ out_reserved_values: log_warn(" Comparison operators:"); t = _op_cmp; for (; t->string; t++) - log_warn(" %4s - %s", t->string, t->desc); + log_warn(" %6s - %s", t->string, t->desc); log_warn(" "); log_warn(" Logical and grouping operators:"); t = _op_log; @@ -2720,6 +2795,7 @@ static struct selection_node *_parse_selection(struct dm_report *rh, struct selection_str_list *str_list; const struct dm_report_reserved_value *reserved; uint64_t factor; + time_t time; void *custom = NULL; char *tmp; char c; @@ -2769,29 +2845,45 @@ static struct selection_node *_parse_selection(struct dm_report *rh, goto bad; } - /* some operators can compare only numeric fields (NUMBER, SIZE or PERCENT) */ - if ((flags & FLD_CMP_NUMBER) && - (ft->flags != DM_REPORT_FIELD_TYPE_NUMBER) && - (ft->flags != DM_REPORT_FIELD_TYPE_SIZE) && - (ft->flags != DM_REPORT_FIELD_TYPE_PERCENT)) { - _display_selection_help(rh); - log_error("Operator can be used only with number, size or percent fields: %s", ws); - goto bad; - } - /* comparison value */ if (flags & FLD_CMP_REGEX) { + /* + * regex value + */ if (!(last = _tok_value_regex(rh, ft, last, &vs, &ve, &flags, &reserved))) goto_bad; } else { - if (ft->flags == DM_REPORT_FIELD_TYPE_SIZE || - ft->flags == DM_REPORT_FIELD_TYPE_NUMBER || - ft->flags == DM_REPORT_FIELD_TYPE_PERCENT) + /* + * number, size, percent, time, string, string_list value + */ + if (flags & FLD_CMP_NUMBER) { + if (!(ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER | + DM_REPORT_FIELD_TYPE_SIZE | + DM_REPORT_FIELD_TYPE_PERCENT | + DM_REPORT_FIELD_TYPE_TIME))) { + _display_selection_help(rh); + log_error("Operator can be used only with number, size, time or percent fields: %s", ws); + goto bad; + } + } else if (flags & FLD_CMP_TIME) { + if (!(ft->flags & DM_REPORT_FIELD_TYPE_TIME)) { + _display_selection_help(rh); + log_error("Operator can be used only with time fields: %s", ws); + goto bad; + } + } + + if (ft->flags & (DM_REPORT_FIELD_TYPE_NUMBER | + DM_REPORT_FIELD_TYPE_SIZE | + DM_REPORT_FIELD_TYPE_PERCENT)) custom = &factor; - else if (ft->flags == DM_REPORT_FIELD_TYPE_STRING_LIST) + else if (ft->flags & DM_REPORT_FIELD_TYPE_TIME) + custom = &time; + else if (ft->flags & DM_REPORT_FIELD_TYPE_STRING_LIST) custom = &str_list; else custom = NULL; + if (!(last = _tok_value(rh, ft, field_num, implicit, last, &vs, &ve, &flags, &reserved, rh->selection->mem, custom))) @@ -3103,7 +3195,8 @@ static int _row_compare(const void *a, const void *b) sfa = (*rowa->sort_fields)[cnt]; sfb = (*rowb->sort_fields)[cnt]; if ((sfa->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) || - (sfa->props->flags & DM_REPORT_FIELD_TYPE_SIZE)) { + (sfa->props->flags & DM_REPORT_FIELD_TYPE_SIZE) || + (sfa->props->flags & DM_REPORT_FIELD_TYPE_TIME)) { const uint64_t numa = *(const uint64_t *) sfa->sort_value; const uint64_t numb = |