1sg_vector_create(3) sg_vector_create(3)
2
3
4
6 sg_vector_create, sg_vector_clear, sg_vector_resize, sg_vector_free,
7 sg_vector_clone, sg_vector_clone_into, sg_vector_compute_diff,
8 sg_prove_vector, sg_get_nelements, sg_free_stats_buf - statgrab vector
9 management
10
12 #include "statgrab.h"
13 #include "vector.h"
14
15
16 struct sg_vector *sg_vector_create (size_t block_size, size_t
17 alloc_count, size_t initial_used,
18 const sg_vector_init_info * const
19 info);
20
21 void sg_vector_clear (struct sg_vector *vector);
22
23 struct sg_vector *sg_vector_resize (struct sg_vector *vector);
24
25 void sg_vector_free (struct sg_vector *vector);
26
27 struct sg_vector *sg_vector_clone (const struct sg_vector *src);
28
29 sg_error sg_vector_clone_into (struct sg_vector **dest, const struct
30 sg_vector *src);
31
32 sg_error sg_vector_compute_diff (struct sg_vector **dest, const struct
33 sg_vector *cur_vector, const struct
34 sg_vector *last_vector);
35
36 sg_error sg_prove_vector (const struct sg_vector *vec);
37
38 size_t sg_get_nelements (const void *data);
39
40 sg_error sg_free_stats_buf (void *data);
41
43 sg_vector_create() allocates and initialises a new statgrab vector with
44 initial_used elements ready for use. Space for alloc_count elements is
45 initially allocated (to avoid too many calls to realloc() during later
46 sg_vector_resize() calls). The value of block_size must be a power of
47 2, it's rounded up to the next power of 2 when it's not. If alloc_count
48 is not a multiple of block_size, it's rounded up to the next multiple
49 of block_size. It returns a pointer to the newly created vector.
50
51 sg_vector_clear() destroys all elements contained in the given vector.
52 In opposite to sg_vector_resize( x, 0 ) the allocated size of the vec‐
53 tor remains untouched.
54
55 sg_vector_resize() increases or decreases the amount of allocated ele‐
56 ments in the specified vector. The amount of allocated elements is al‐
57 ways a multiple of the initialisation parameter block_size. In the spe‐
58 cial case, sg_vector_resize() is called with 0 in argument new_count,
59 the vector is freed after all vector elements had been destroyed. It
60 returns the pointer to the resized vector.
61
62 sg_vector_free() destroys all vector elements and deallocates the stor‐
63 age belonging to the given vector.
64
65 sg_vector_clone() clones all elements of the given vector into a new
66 vector created with the same specification as the referenced one. It
67 returns a pointer to the cloned vector.
68
69 sg_vector_clone_into() clones all elements of the given source vector
70 into the given target vector. The target vector must be created for the
71 same element data type as the source vector. It returns an error code
72 != to SG_ERROR_NONE if something went wrong.
73
74 sg_vector_compute_diff() computes a difference vector between the vec‐
75 tor containing current statistics and another vector containing older
76 statistics. If an element exists in the current vector but not in the
77 opposite one, it's cloned into the result vector. If an element exists
78 only in the opposite vector, it doesn't appear in the target vector.
79 sg_vector_compute_diff() returns an error code != to SG_ERROR_NONE if
80 something went wrong.
81
82 sg_prove_vector() proves whether a pointer to a vector really points to
83 a vector. In case the given vector pointer points to corrupted data,
84 the program is aborted. When sg_prove_vector() returns, it returns
85 SG_ERROR_NONE.
86
87 sg_get_nelements() returns the number of elements the given data area,
88 encompasses by a statgrab vector, contains. The vector head is inter‐
89 nally calculated from the given pointer to the first vector element.
90
91 sg_free_stats_buf() frees the vector emcompassing the given data area.
92
94 Except sg_get_nelements() and sg_free_stats_buf() none of above func‐
95 tions can be called from outside of the libstatgrab sources. The docu‐
96 mented structures and APIs may change without warning. The description
97 of all other API is intended to be read from libstatgrab developers on‐
98 ly.
99
100 Each vector is created from two elements: the vector information and
101 the list of elements:
102
103 template <class T, class Impl>
104 struct sg_vector {
105 size_t used_count;
106 size_t alloc_count;
107 size_t block_shift;
108 Impl vector_implementation;
109 T elements[alloc_count];
110 };
111
112
113 Of course, it is not valid C, so being tricky was the solution:
114
115 typedef struct sg_vector {
116 size_t used_count;
117 size_t alloc_count;
118 size_t block_shift;
119 struct sg_vector_init_info info;
120 } sg_vector;
121
122 struct sg_vector_size_helper {
123 struct sg_vector v;
124 long long ll;
125 };
126
127 #define VECTOR_SIZE offsetof(struct sg_vector_size_helper,ll)
128
129 /* Return the data ptr of a vector */
130 #define VECTOR_DATA(vector) \
131 (vector ? (void *)(((char *)vector)+VECTOR_SIZE) : NULL)
132
133 #define VECTOR_ADDR_ARITH(ptr) \
134 (sg_vector *)(((char *)(ptr))-VECTOR_SIZE)
135 /* Return the vector for a data */
136 #define VECTOR_ADDRESS(ptr) \
137 ((ptr) ? (SG_ERROR_NONE == sg_prove_vector(VECTOR_ADDR_ARITH(ptr)) ? VECTOR_ADDR_ARITH(ptr) : NULL ) : NULL)
138
139
140 This also allows user functions as sg_get_nelements() and
141 sg_free_stats_buf() to switch easily between the vector structure and
142 the content.
143
144 THE VECTOR SPECIALISATION STRUCTURE
145 As mentioned, the vector implementation uses strategies from the object
146 oriented programming concept named "polymorphism". A vector is de‐
147 scribed by a small object containing inherent attributes like element
148 size and a bunch of "virtual methods" to do element related tasks like
149 initialising or destroying elements.
150
151 typedef void (*vector_init_function)(void *item);
152 typedef sg_error (*vector_copy_function)(const void *src, void *dst);
153 typedef sg_error (*vector_compute_diff_function)(void *dst, const void *src);
154 typedef int (*vector_compare_function)(const void *a, const void *b);
155 typedef void (*vector_destroy_function)(void *item);
156
157 struct sg_vector_init_info {
158 size_t item_size;
159 vector_init_function init_fn;
160 vector_copy_function copy_fn;
161 vector_compute_diff_function compute_diff_fn;
162 vector_compare_function compare_fn;
163 vector_destroy_function destroy_fn;
164 };
165
166
167 The instances of struct sg_vector_init_info are conceptional statically
168 initialised by using either the preprocessor macro VECTOR_INIT_IN‐
169 FO_FULL_INIT(type) or VECTOR_INIT_INFO_EMPTY_INIT(type). Here're some
170 examples to demonstrate how it's meant:
171
172 Initialising CPU statistics vector description
173
174 VECTOR_INIT_INFO_EMPTY_INIT(sg_cpu_stats);
175
176
177 Initialising Host-Info statistics vector description
178
179 static void sg_os_stats_item_init(sg_os_stats *d);
180 static void sg_os_stats_item_destroy(sg_os_stats *d);
181
182 #define sg_os_stats_item_copy NULL
183 #define sg_os_stats_item_compute_diff NULL
184 #define sg_os_stats_item_compare NULL
185
186 VECTOR_INIT_INFO_FULL_INIT(sg_os_stats);
187
188
189 Initialising Disk-IO statistics vector description
190
191 static void sg_disk_io_stats_item_init(sg_disk_io_stats *d);
192 static sg_error sg_disk_io_stats_item_copy(sg_disk_io_stats *d, const sg_disk_io_stats *s);
193 static sg_error sg_disk_io_stats_item_compute_diff(const sg_disk_io_stats *s, sg_disk_io_stats *d);
194 static int sg_disk_io_stats_item_compare(const sg_disk_io_stats *a, const sg_disk_io_stats *b);
195 static void sg_disk_io_stats_item_destroy(sg_disk_io_stats *d);
196
197 VECTOR_INIT_INFO_FULL_INIT(sg_disk_io_stats);
198
199
200 WORKING WITH VECTORS
201 To simplify the working with the vector management functions, some pre‐
202 processor macros are available. They are shown here as if they were
203 functions to ease understanding.
204
205 struct sg_vector *VECTOR_CREATE (identifier type, size_t block_size);
206
207 void VECTOR_CLEAR (struct sg_vector *vector);
208
209 struct sg_vector *VECTOR_CREATE_OR_RESIZE (struct sg_vector *vector,
210 size_t new_count, identifier type);
211
212 void VECTOR_UPDATE (struct sg_vector **vectorptr, size_t new_count,
213 datatype *data, identifier datatype);
214
215 void VECTOR_ITEM_COUNT (struct sg_vector *vector);
216
217 VECTOR_CREATE() calls sg_vector_create() with alloc_count = block_size
218 and initial_used = 0 using the vector specialisation type##_vec‐
219 tor_init_info.
220
221 VECTOR_CLEAR() simply calls sg_vector_clear(). This macro exists only
222 for conformity.
223
224 VECTOR_CREATE_OR_RESIZE() calls sg_vector_create() when the given vec‐
225 tor pointer points to NULL or sg_vector_resize() otherwise. The result
226 of the appropriate function is returned.
227
228 VECTOR_UPDATE() calls VECTOR_CREATE_OR_RESIZE() and sets data to the
229 first element of the resulting vector when a non-NULL pointer got, to
230 NULL otherwise. When VECTOR_CREATE_OR_RESIZE() returns a NULL pointer
231 and new_count is not equal to 0 (zero), the instructions from the macro
232 VECTOR_UPDATE_ERROR_CLEANUP are executed to cleanup before returning
233 from current subroutine with the error which has been occurred.
234
235 VECTOR_ITEM_COUNT() returns 0 for a non-existing vector (vector == 0)
236 and the number of containing elements otherwise.
237
239 Beside error codes, the return values, if any, are always a pointer to
240 vector structures (struct sg_vector *).
241
243 statgrab(3)
244
246 ⟨https://libstatgrab.org/⟩
247
248
249
250libstatgrab 2019-10-03 sg_vector_create(3)