1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00
lvm2/lib/properties/prop_common.h

139 lines
5.2 KiB
C
Raw Permalink Normal View History

/*
* Copyright (C) 2013 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LVM_PROP_COMMON_H
#define _LVM_PROP_COMMON_H
#include <stdint.h>
/*
* Common code for getting and setting properties.
*/
struct lvm_property_type {
unsigned type;
const char *id;
unsigned is_settable:1;
unsigned is_string:1;
unsigned is_integer:1;
lvm2app: Add signed numerical property values Currently lvm2app properties have the following structure: typedef struct lvm_property_value { uint32_t is_settable:1; uint32_t is_string:1; uint32_t is_integer:1; uint32_t is_valid:1; uint32_t padding:28; union { const char *string; uint64_t integer; } value; } lvm_property_value_t; which assumes that numerical values were in the range of 0 to 2**64-1. However, some of the properties were 'signed', like LV major/minor numbers and some reserved values for properties that represent percentages. Thus when the values were retrieved they were in two's complement notation. So for a -1 major number the API user would get a value of 18446744073709551615. The API user could cast the returned value to an int64_t to handle this, but that requires the API developer to look at the source code and determine when it should be done. This change modifies the return property structure to: typedef struct lvm_property_value { uint32_t is_settable:1; uint32_t is_string:1; uint32_t is_integer:1; uint32_t is_valid:1; uint32_t is_signed:1; uint32_t padding:27; union { const char *string; uint64_t integer; int64_t signed_integer; } value; } lvm_property_value_t; With this addition the API user can interrogate that the value is numerical, (is_integer = 1) and subsequently check if it's signed (is_signed = 1) too. If signed, then the API developer should use the union's signed_integer to avoid casting. This change maintains backwards compatibility as the structure size remains unchanged and integer value remains unchanged. Only the additional bit taken from the pad is utilized. Bugzilla reference: https://bugzilla.redhat.com/show_bug.cgi?id=838257 Signed-off-by: Tony Asleson <tasleson@redhat.com>
2015-05-04 22:51:41 +03:00
unsigned is_signed:1;
union {
const char *string;
uint64_t integer;
lvm2app: Add signed numerical property values Currently lvm2app properties have the following structure: typedef struct lvm_property_value { uint32_t is_settable:1; uint32_t is_string:1; uint32_t is_integer:1; uint32_t is_valid:1; uint32_t padding:28; union { const char *string; uint64_t integer; } value; } lvm_property_value_t; which assumes that numerical values were in the range of 0 to 2**64-1. However, some of the properties were 'signed', like LV major/minor numbers and some reserved values for properties that represent percentages. Thus when the values were retrieved they were in two's complement notation. So for a -1 major number the API user would get a value of 18446744073709551615. The API user could cast the returned value to an int64_t to handle this, but that requires the API developer to look at the source code and determine when it should be done. This change modifies the return property structure to: typedef struct lvm_property_value { uint32_t is_settable:1; uint32_t is_string:1; uint32_t is_integer:1; uint32_t is_valid:1; uint32_t is_signed:1; uint32_t padding:27; union { const char *string; uint64_t integer; int64_t signed_integer; } value; } lvm_property_value_t; With this addition the API user can interrogate that the value is numerical, (is_integer = 1) and subsequently check if it's signed (is_signed = 1) too. If signed, then the API developer should use the union's signed_integer to avoid casting. This change maintains backwards compatibility as the structure size remains unchanged and integer value remains unchanged. Only the additional bit taken from the pad is utilized. Bugzilla reference: https://bugzilla.redhat.com/show_bug.cgi?id=838257 Signed-off-by: Tony Asleson <tasleson@redhat.com>
2015-05-04 22:51:41 +03:00
int64_t signed_integer;
} value;
int (*get) (const void *obj, struct lvm_property_type *prop);
int (*set) (void *obj, struct lvm_property_type *prop);
};
int prop_not_implemented_get(const void *obj, struct lvm_property_type *prop);
int prop_not_implemented_set(void *obj, struct lvm_property_type *prop);
int prop_get_property(struct lvm_property_type *p, const void *obj,
struct lvm_property_type *prop,
unsigned type);
int prop_set_property(struct lvm_property_type *p, void *obj,
struct lvm_property_type *prop,
unsigned type);
#define GET_NUM_PROPERTY_FN(NAME, VALUE, TYPE, VAR) \
static int _ ## NAME ## _get (const void *obj, struct lvm_property_type *prop) \
{ \
const struct TYPE *VAR = (const struct TYPE *)obj; \
\
prop->value.integer = VALUE; \
return 1; \
}
#define SET_NUM_PROPERTY_FN(NAME, SETFN, TYPE, VAR) \
static int _ ## NAME ## _set (void *obj, struct lvm_property_type *prop) \
{ \
struct TYPE *VAR = (struct TYPE *)obj; \
\
SETFN(VAR, prop->value.integer); \
return 1; \
}
#define SET_NUM_PROPERTY(NAME, VALUE, TYPE, VAR) \
static int _ ## NAME ## _set (void *obj, struct lvm_property_type *prop) \
{ \
struct TYPE *VAR = (struct TYPE *)obj; \
\
VALUE = prop->value.integer; \
return 1; \
}
#define GET_STR_PROPERTY_FN(NAME, VALUE, TYPE, VAR) \
static int _ ## NAME ## _get (const void *obj, struct lvm_property_type *prop) \
{ \
const struct TYPE *VAR = (const struct TYPE *)obj; \
\
prop->value.string = (char *)VALUE; \
return 1; \
}
/*
* The 'FIELD' macro arguments are defined as follows:
* 1. report_type. An enum value that selects a specific
* struct dm_report_object_type in the _report_types array. The value is
* used to select the containing base object address (see *obj_get*
* functions) for any data values of any field in the report.
* 2. Containing struct. The structure that either contains the field data
* as a member or should be used to obtain the field data. The containing
* struct should match the base object of the report_type.
* 3. Field type. This must be either 'STR' or 'NUM'.
* 4. Report heading. This is the field heading that is displayed by the
* reporting commands.
* 5. Data value pointer. This argument is always a member of the
* containing struct. It may point directly to the data value (for example,
* lv_uuid - see _uuid_disp()) or may be used to derive the data value (for
* example, seg_count - see _lvsegcount_disp()). In the FIELD macro
* definition, it is used in an offset calculation to derive the offset to
* the data value from the containing struct base address. Note that in some
* cases, the argument is the first member of the struct, in which case the
* data value pointer points to the start of the struct itself (for example,
* 'lvid' field of struct 'lv').
* 6. Minimum display width. This is the minimum width used to display
* the field value, typically matching the width of the column heading.
* 7. Display function identifier. Used to derive the full name of the
* function that displays this field. Derivation is done by appending '_'
* then prepending this argument to '_disp'. For example, if this argument
* is 'uuid', the display function is _uuid_disp(). Adding a new field may
* require defining a new display function (for example _myfieldname_disp()),
* or reuse of an existing one (for example, _uint32_disp()).
* 8. Unique format identifier / field id. This name must be unique and is
* used to select fields via '-o' in the reporting commands (pvs/vgs/lvs).
* The string used to specify the field - the 'id' member of
* struct dm_report_field_type.
* 9. Description of field. This is a brief (ideally <= 52 chars) description
* of the field used in the reporting commands.
* 10. Flags.
* FIELD_MODIFIABLE. A '_set' function exists to change the field's value.
* The function name is derived in a similar way to item 7 above.
*/
#define STR 1
#define NUM 2
2014-07-02 13:09:14 +04:00
#define BIN 3
#define SIZ 4
#define PCT 5
report: add support for time (basic) This patch adds support for time values used in reporting fields. The raw values are always stored as number of seconds since epoch. The support that comes with this patch is the basic one which allows only for recognition of strictly formatted date and time in selection criteria (the format follows a subset of formats defined by ISO 8601): date time timezone date: YYYY-MM-DD (or shortly YYYYMMDD) YYYY-MM (shortly YYYYMM), auto DD=1 YYYY, auto MM=01 and DD=01 time: hh:mm:ss (or shortly hhmmss) hh:mm (or shortly hhmm), auto ss=0 hh (or shortly hh), auto mm=0, auto ss=0 timezone (always with + or - sign): +hh:mm or -hh:mm (or shortly +hhmm or -hhmm) +hh or -hh Or directly the time (number of seconds) since Epoch (1970-01-01 00:00:00 UTC) when the number value is prefixed by "@": @number_of_seconds_since_epoch This patch also adds aliases for comparison operators used together with time values which are more intuitive to use: since (as alias for >=) after (as alias for >) until (as alias for <=) before (as alias for <) For example: $ lvmconfig --type full report/time_format time_format="%Y-%m-%d %T %z %Z [%s]" $ lvs -o name,time vg LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] lvol2 2015-04-26 14:52:20 +0200 CEST [1430052740] lvol3 2015-06-30 14:52:23 +0200 CEST [1435668743] $ lvs vg -o name,time -S 'time since "2015-04-26 15:00" && time until "2015-06-30"' LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] lvol3 2015-06-30 14:52:23 +0200 CEST [1435668743] $ lvs vg -o name,time -S 'time since "2015-04-26 15:00" && time until "2015-06-30 6:00"' LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] $ lvs vg -o name,time -S 'time since @1435519541' LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] lvol3 2015-06-30 14:52:23 +0200 CEST [1435668743] This is basic time recognition support that is directly a part of libdevmapper. Recognition of more free-form expressions will be a part of subsequent patches.
2015-05-21 16:19:03 +03:00
#define TIM 6
lvm2app: Add signed numerical property values Currently lvm2app properties have the following structure: typedef struct lvm_property_value { uint32_t is_settable:1; uint32_t is_string:1; uint32_t is_integer:1; uint32_t is_valid:1; uint32_t padding:28; union { const char *string; uint64_t integer; } value; } lvm_property_value_t; which assumes that numerical values were in the range of 0 to 2**64-1. However, some of the properties were 'signed', like LV major/minor numbers and some reserved values for properties that represent percentages. Thus when the values were retrieved they were in two's complement notation. So for a -1 major number the API user would get a value of 18446744073709551615. The API user could cast the returned value to an int64_t to handle this, but that requires the API developer to look at the source code and determine when it should be done. This change modifies the return property structure to: typedef struct lvm_property_value { uint32_t is_settable:1; uint32_t is_string:1; uint32_t is_integer:1; uint32_t is_valid:1; uint32_t is_signed:1; uint32_t padding:27; union { const char *string; uint64_t integer; int64_t signed_integer; } value; } lvm_property_value_t; With this addition the API user can interrogate that the value is numerical, (is_integer = 1) and subsequently check if it's signed (is_signed = 1) too. If signed, then the API developer should use the union's signed_integer to avoid casting. This change maintains backwards compatibility as the structure size remains unchanged and integer value remains unchanged. Only the additional bit taken from the pad is utilized. Bugzilla reference: https://bugzilla.redhat.com/show_bug.cgi?id=838257 Signed-off-by: Tony Asleson <tasleson@redhat.com>
2015-05-04 22:51:41 +03:00
#define SNUM 7 /* Signed Number */
report: add support for time (basic) This patch adds support for time values used in reporting fields. The raw values are always stored as number of seconds since epoch. The support that comes with this patch is the basic one which allows only for recognition of strictly formatted date and time in selection criteria (the format follows a subset of formats defined by ISO 8601): date time timezone date: YYYY-MM-DD (or shortly YYYYMMDD) YYYY-MM (shortly YYYYMM), auto DD=1 YYYY, auto MM=01 and DD=01 time: hh:mm:ss (or shortly hhmmss) hh:mm (or shortly hhmm), auto ss=0 hh (or shortly hh), auto mm=0, auto ss=0 timezone (always with + or - sign): +hh:mm or -hh:mm (or shortly +hhmm or -hhmm) +hh or -hh Or directly the time (number of seconds) since Epoch (1970-01-01 00:00:00 UTC) when the number value is prefixed by "@": @number_of_seconds_since_epoch This patch also adds aliases for comparison operators used together with time values which are more intuitive to use: since (as alias for >=) after (as alias for >) until (as alias for <=) before (as alias for <) For example: $ lvmconfig --type full report/time_format time_format="%Y-%m-%d %T %z %Z [%s]" $ lvs -o name,time vg LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] lvol2 2015-04-26 14:52:20 +0200 CEST [1430052740] lvol3 2015-06-30 14:52:23 +0200 CEST [1435668743] $ lvs vg -o name,time -S 'time since "2015-04-26 15:00" && time until "2015-06-30"' LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] lvol3 2015-06-30 14:52:23 +0200 CEST [1435668743] $ lvs vg -o name,time -S 'time since "2015-04-26 15:00" && time until "2015-06-30 6:00"' LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] $ lvs vg -o name,time -S 'time since @1435519541' LV Time lvol0 2015-06-28 21:25:41 +0200 CEST [1435519541] lvol1 2015-06-30 03:25:43 +0200 CEST [1435627543] lvol3 2015-06-30 14:52:23 +0200 CEST [1435668743] This is basic time recognition support that is directly a part of libdevmapper. Recognition of more free-form expressions will be a part of subsequent patches.
2015-05-21 16:19:03 +03:00
#define STR_LIST 8
#define FIELD_MODIFIABLE 0x00000001
#define FIELD(type, strct, field_type, head, field, width, fn, id, desc, settable) \
{ type, #id, settable, (field_type == STR || field_type == STR_LIST), ((field_type == NUM) || (field_type == BIN) || (field_type == SIZ) || (field_type == PCT) || (field_type == SNUM)), ((field_type == SNUM) || (field_type == PCT)), { .integer = 0 }, _ ## id ## _get, _ ## id ## _set },
#endif