'\" -*- coding: UTF-8 -*- .if \n(.g .ds T< \\FC .if \n(.g .ds T> \\F[\n[.fam]] .de URL \\$2 \(la\\$1\(ra\\$3 .. .if \n(.g .mso www.tmac .TH sg_comp_init 3 2019-10-03 libstatgrab "" .SH NAME sg_comp_init, sg_comp_destroy, sg_comp_get_tls, sg_global_lock, sg_global_unlock \- managing system statistics delivery .SH SYNOPSIS 'nh .nf \*(T<#include "tools.h"\*(T> .fi .sp 1 .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(unsigned int \fIid\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(void);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(void);\*(T> 'in \n(.iu-\nxu .ad b 'hy .SH DESCRIPTION \*(T<\fBsg_comp_init\fR\*(T>() is called by \*(T<\fBsg_init\fR\*(T>() 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 \*(T) to the \*(T list in \*(T<\fIsrc/libstatgrab/globals.c\fR\*(T>. The instance of \*(T is usually defined by using one of \*(T<\fBEASY_COMP_SETUP\fR\*(T>() or \*(T<\fBEXTENDED_COMP_SETUP\fR\*(T>(), respectively. .PP \*(T<\fBsg_comp_destroy\fR\*(T>() is called by \*(T<\fBsg_shutdown\fR\*(T>() 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 \*(T<\fBsg_comp_destroy\fR\*(T>() is invoked. .PP \*(T<\fBsg_comp_get_tls\fR\*(T>() 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 \*(T<\fBGLOBAL_GET_TLS\fR\*(T>(). .SH NOTES 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: .TP 0.4i 1. declare component's global and TLS data structure (probably only on paper, not in code) .TP 0.4i 2. define global initialisation, thread destruction and process destruction functions (if required by 1.) .TP 0.4i 3. define component information structure using \*(T<\fB*_COMP_SETUP\fR\*(T>() .TP 0.4i 4. define component accessors using one or more of \*(T<\fBEASY_COMP_ACCESS\fR\*(T>() .br \*(T<\fBEASY_COMP_DIFF\fR\*(T>() .br \*(T<\fBMULTI_COMP_ACCESS\fR\*(T>() .br \*(T<\fBMULTI_COMP_DIFF\fR\*(T>() .PP When having done these steps, a new component delivering new statistics is born and needs to be "announced". Assuming the component is named \fIcpu\fR, append the line \*(T<{ &sg_cpu_init, 0 }\*(T> to above named \*(T list. .PP Component initialisation information in detail: .nf \*(T< 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; }; \*(T> .fi Components which do not need something special can rely on \*(T<\fBEASY_COMP_SETUP\fR\*(T>(): \fBInitialising memory component\fR .PP .nf \*(T< EASY_COMP_SETUP(mem,1,NULL); \*(T> .fi When own initialisation is needed, doing it is a bit more complex: \fBInitialising network component\fR .PP .nf \*(T< #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) \*(T> .fi .SS "MACROS TO WORK WITH THE COMPONENT MANAGER" 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. .PP 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR, \fI...\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR, size_t \fInvect\fR, \fI...\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR, size_t \fInvect\fR, \fI...\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR, unsigned int \fIid\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIcomp\fR, size_t \fInvect\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIfn\fR, identifier \fIcomp\fR, identifier \fIstat\fR, size_t \fIidx\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIfn\fR, identifier \fIcomp\fR, identifier \fIstat\fR, size_t \fIidx\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIfn\fR, identifier \fIgetfn\fR, identifier \fIcomp\fR, identifier \fIstat\fR, size_t \fIdiffidx\fR, size_t \fInowidx\fR);\*(T> 'in \n(.iu-\nxu .ad b .PP .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(identifier \fIfn\fR, identifier \fIgetfn\fR, identifier \fIcomp\fR, identifier \fIstat\fR, size_t \fIdiffidx\fR, size_t \fInowidx\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy .PP \*(T<\fBEASY_COMP_SETUP\fR\*(T>() cares about anything to be automatically done for instantiating a component information structure for the specified component \*(T. The created TLS storage structure will hold \*(T pointer elements and that's it. All initialisation, destruction and cleanup-routines are created as needed using \*(T<\fBEASY_COMP_INIT_FN\fR\*(T>(), \*(T<\fBEASY_COMP_DESTROY_FN\fR\*(T>() and \*(T<\fBEASY_COMP_CLEANUP_FN\fR\*(T>(). After the amount of required vector pointers to be stored the list of required mutexes must be specified, finished with a NULL pointer. .PP \*(T<\fBEXTENDED_COMP_SETUP\fR\*(T>() cares about anything to be automatically done for instantiating an component information structure for the specified component \*(T but the required definition of the initialisation, destruction and cleanup routines. The created TLS storage structure will hold \*(T 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 \*(T<\fBEASY_COMP_INIT_FN\fR\*(T>(), \*(T<\fBEASY_COMP_DESTROY_FN\fR\*(T>() and \*(T<\fBEASY_COMP_CLEANUP_FN\fR\*(T>(). .PP \*(T<\fBDEFAULT_INIT_COMP\fR\*(T>() 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. .PP \*(T<\fBGLOBAL_GET_TLS\fR\*(T>() returns the pointer to the component's \fIthread local storage\fR. .PP \*(T<\fBGLOBAL_SET_ID\fR\*(T>() stores the component identifier, required eg. to access its TLS. .PP \*(T<\fBEASY_COMP_INIT_FN\fR\*(T>() defines a default component initialisation routine. It stores the component identifier and returns with SG_ERROR_NONE. .PP \*(T<\fBEASY_COMP_DESTROY_FN\fR\*(T>() defines a default component destructor, called at the end of the entire process (or when the last \*(T<\fBsg_shutdown\fR\*(T>() is called). The default destructor does nothing and usually an individual initialisation routine requires an individual destructor, too. .PP \*(T<\fBEASY_COMP_CLEANUP_FN\fR\*(T>() defines a default TLS cleanup routine, always called when a thread ends to free vectors held in \fIthread local storage\fR. .PP \*(T<\fBEASY_COMP_ACCESS\fR\*(T>() defines accessors to a specific statistic containing one element provided by the component: the functions \*(T<\fBfn\fR\*(T>() and the \*(T<\fBfn##_r\fR\*(T>(). The following function must exists: 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(sg_vector *\fIname##_vect\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy It accesses the vector idx from TLS of component \*(T and returns sg_##name##_stats. It manages all standard things like memory and error management, return value etc. .PP \*(T<\fBEASY_COMP_DIFF\fR\*(T>() 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 \*(T and the resulting vector of \*(T<\fBgetfn\fR\*(T>(). The result is stored in the vector \*(T. If there is no current result, simply the result of \*(T<\fBgetfn\fR\*(T>() is returned. .PP \*(T<\fBMULTI_COMP_ACCESS\fR\*(T>() defines accessors to a specific statistic containing 0..n elements provided by the component: the functions \*(T<\fBfn\fR\*(T>() and the \*(T<\fBfn##_r\fR\*(T>(). The following function must exists: 'nh .fi .ad l \*(T \kx .if (\nx>(\n(.l/2)) .nr x (\n(.l/5) 'in \n(.iu+\nxu \*(T<(sg_vector **\fIname##_vect\fR);\*(T> 'in \n(.iu-\nxu .ad b 'hy It accesses the vector idx from TLS of component \*(T and returns sg_##name##_stats. It manages all standard things like memory and error anagement, return values, \*(T update, etc. .PP \*(T<\fBMULTI_COMP_DIFF\fR\*(T>() does the same as \*(T<\fBEASY_COMP_DIFF\fR\*(T>() but for vectors with more than one element. .SH "SEE ALSO" \fBlibstatgrab\fR(3) \fBsg_intro\fR(3) \fBsg_set_error\fR(3) \fBsg_comp_init\fR(3) \fBsg_vector_create\fR(3) .SH WEBSITE \(lahttps://libstatgrab.org/\(ra