sg_comp_init, sg_comp_destroy, sg_comp_get_tls, sg_global_lock, sg_global_unlock — managing system statistics delivery
#include "tools.h"
void *get_global_static( | id) ; |
unsigned int id
;sg_error sg_global_lock( | ) ; |
sg_error sg_global_unlock( | ) ; |
sg_comp_init
() is called by
sg_init
() to run the initialisation for the
globals component and each registered libstatgrab component. This
registration is done statically by appending a component
initialisation information structure
(instance-of sg_comp_info) to the
comp_info
list in
src/libstatgrab/globals.c
. The instance of
sg_comp_info is usually defined by using
one of EASY_COMP_SETUP
() or
EXTENDED_COMP_SETUP
(), respectively.
sg_comp_destroy
() is called by
sg_shutdown
() to destroy all global resources,
eg. translation tables for device names or compiled regular
expressions to match path names etc. Statistics resources are managed
somewhere else and are freed (conceptually and usually) before
sg_comp_destroy
() is invoked.
sg_comp_get_tls
() is the internal function
to access the thread local storage (formerly static globals) of the
component. Usually it's easier to rely on the encapsulating macro
GLOBAL_GET_TLS
().
Delivering system statistics is the job of libstatgrab, managing the delivery is the job of the globals component. To fulfil this job, the components to manage must be prepared:
*_COMP_SETUP
()EASY_COMP_ACCESS () |
EASY_COMP_DIFF () |
MULTI_COMP_ACCESS () |
MULTI_COMP_DIFF () |
When having done these steps, a new component delivering new
statistics is born and needs to be "announced". Assuming
the component is named cpu, append the line
{ &sg_cpu_init, 0 }
to above named
comp_info
list.
Component initialisation information in detail:
typedef sg_error (*comp_global_init_function)(unsigned id); typedef void (*comp_global_destroy_function)(void); typedef void (*comp_global_cleanup_function)(void *); struct sg_comp_status { sg_error init_error; }; struct sg_comp_init { comp_global_init_function init_fn; comp_global_destroy_function destroy_fn; comp_global_cleanup_function cleanup_fn; size_t static_buf_size; #if defined(ENABLE_THREADS) && defined(HAVE_PTHREAD) const char **required_locks; #endif struct sg_comp_status *status; };
Components which do not need something special can rely on
EASY_COMP_SETUP
():
When own initialisation is needed, doing it is a bit more complex:
Example 2. Initialising network component
#define SG_NETWORK_IO_NOW_IDX 0 #define SG_NETWORK_IO_DIFF_IDX 1 #define SG_NETWORK_IFACE_IDX 2 #define SG_NETWORK_MAX_IDX 3 EXTENDED_COMP_SETUP(network,SG_NETWORK_MAX_IDX,NULL); #ifdef LINUX static regex_t network_io_rx; #define RX_MATCH_COUNT (8+1) #endif sg_error sg_network_init_comp(unsigned id) { GLOBAL_SET_ID(network,id); #ifdef LINUX if( regcomp( &network_io_rx, ..., REG_EXTENDED)!=0) { return sg_set_error(SG_ERROR_PARSE, NULL); } #endif return SG_ERROR_NONE; } void sg_network_destroy_comp(void) { #ifdef LINUX regfree(&network_io_rx); #endif } EASY_COMP_CLEANUP_FN(network,SG_NETWORK_MAX_IDX)
To simplify working with the component management functions, some preprocessor macros are available. They are shown here as if they were functions to ease understanding.
void DEFAULT_INIT_COMP( | comp, | |
...) ; |
identifier comp
;...
;void EASY_COMP_SETUP( | comp, | |
nvect, | ||
...) ; |
identifier comp
;size_t nvect
;...
;void EXTENDED_COMP_SETUP( | comp, | |
nvect, | ||
...) ; |
identifier comp
;size_t nvect
;...
;void GLOBAL_SET_ID( | comp, | |
id) ; |
identifier comp
;unsigned int id
;struct sg_##comp##_glob *GLOBAL_GET_TLS( | comp) ; |
identifier comp
;void EASY_COMP_INIT_FN( | comp) ; |
identifier comp
;void EASY_COMP_DESTROY_FN( | comp) ; |
identifier comp
;void EASY_COMP_CLEANUP_FN( | comp, | |
nvect) ; |
identifier comp
;size_t nvect
;void EASY_COMP_ACCESS( | fn, | |
comp, | ||
stat, | ||
idx) ; |
identifier fn
;identifier comp
;identifier stat
;size_t idx
;void MULTI_COMP_ACCESS( | fn, | |
comp, | ||
stat, | ||
idx) ; |
identifier fn
;identifier comp
;identifier stat
;size_t idx
;void EASY_COMP_DIFF( | fn, | |
getfn, | ||
comp, | ||
stat, | ||
diffidx, | ||
nowidx) ; |
identifier fn
;identifier getfn
;identifier comp
;identifier stat
;size_t diffidx
;size_t nowidx
;void MULTI_COMP_DIFF( | fn, | |
getfn, | ||
comp, | ||
stat, | ||
diffidx, | ||
nowidx) ; |
identifier fn
;identifier getfn
;identifier comp
;identifier stat
;size_t diffidx
;size_t nowidx
;
EASY_COMP_SETUP
() cares about anything to be
automatically done for instantiating a component information
structure for the specified component comp
.
The created TLS storage structure will hold
nvect
pointer elements and that's it.
All initialisation, destruction and cleanup-routines are created
as needed using EASY_COMP_INIT_FN
(),
EASY_COMP_DESTROY_FN
() and
EASY_COMP_CLEANUP_FN
(). After the amount of
required vector pointers to be stored the list of required mutexes
must be specified, finished with a NULL pointer.
EXTENDED_COMP_SETUP
() cares about anything
to be automatically done for instantiating an component information
structure for the specified component comp
but the required definition of the initialisation, destruction and
cleanup routines. The created TLS storage structure will hold
nvect
pointer elements and that's it. After
the amount of required vector pointers to be stored, the list of
required mutexes must be specified, finished with a NULL pointer.
All standard routines can be created semi-automatically using
EASY_COMP_INIT_FN
(),
EASY_COMP_DESTROY_FN
() and
EASY_COMP_CLEANUP_FN
().
DEFAULT_INIT_COMP
() just declares the
prototypes for the initialisation, destruction and cleanup routines,
defines the initialisation status buffer, lock-names list and
finally fills the component initialisation structure.
Use this when your TLS storage contains not only vector pointers.
GLOBAL_GET_TLS
() returns the pointer to the
component's thread local storage.
GLOBAL_SET_ID
() stores the component
identifier, required eg. to access its TLS.
EASY_COMP_INIT_FN
() defines a default
component initialisation routine. It stores the component
identifier and returns with SG_ERROR_NONE.
EASY_COMP_DESTROY_FN
() defines a default
component destructor, called at the end of the entire process
(or when the last sg_shutdown
() is called).
The default destructor does nothing and usually an individual
initialisation routine requires an individual destructor, too.
EASY_COMP_CLEANUP_FN
() defines a default
TLS cleanup routine, always called when a thread ends to free
vectors held in thread local storage.
EASY_COMP_ACCESS
() defines accessors to a
specific statistic containing one element provided by the
component: the functions
fn
() and the fn##_r
().
The following function must exists:
sg_error fn##_int( | name##_vect) ; |
sg_vector *name##_vect
;
It accesses the vector idx from TLS of component
comp
and returns sg_##name##_stats.
It manages all standard things like memory and error management,
return value etc.
EASY_COMP_DIFF
() returns the difference between
the two statistic collection runs. The variant dealing with statgrab
owned statistics return the difference between the content currently
in the vector specified by nowidx
and the
resulting vector of getfn
(). The result is
stored in the vector diffidx
. If there is no
current result, simply the result of getfn
()
is returned.
MULTI_COMP_ACCESS
() defines accessors to a
specific statistic containing 0..n elements provided by the
component: the functions
fn
() and the fn##_r
().
The following function must exists:
sg_error fn##_int( | name##_vect) ; |
sg_vector **name##_vect
;
It accesses the vector idx from TLS of component
comp
and returns sg_##name##_stats.
It manages all standard things like memory and error anagement,
return values, entries
update, etc.
MULTI_COMP_DIFF
() does the same as
EASY_COMP_DIFF
() but for vectors with more than
one element.