ROFL-pipeline  v0.6.0dev
monitoring.c
1 #include "monitoring.h"
2 #include <assert.h>
3 #include <string.h>
5 #include "platform/lock.h"
6 #include "platform/memory.h"
7 #include "util/logging.h"
8 
9 //
10 // Monitored entities
11 //
12 
13 static inline void __clone_copy_me_fields(monitored_entity_t* d, monitored_entity_t* orig){
14 
15  //Copy contents rawly
16  memcpy(d,orig,sizeof(monitored_entity_t));
17 
18  //Set pointers to NULL
19  d->parent=d->inner=d->prev=d->next=NULL;
20 }
21 
22 //clones the monitored entity, and all next and inner ones
23 static inline monitored_entity_t* __clone_monitored_entity(monitored_entity_t* orig){
24 
25  monitored_entity_t* entity;
26 
27  if(!orig)
28  return NULL;
29 
30  //Create a new entity
32 
33  if(!entity)
34  return NULL;
35  //memset to zero
36  platform_memset(entity,0,sizeof(*entity));
37 
38  //Clone fields
39  __clone_copy_me_fields(entity, orig);
40 
41  //Launch recursively the copies over the inner and the next
42  if(orig->inner){
43  entity->inner = __clone_monitored_entity(orig->inner);
44  if(!entity->inner){
45  assert(0);
46  }
47  }
48  if(orig->next){
49  entity->next = __clone_monitored_entity(orig->next);
50  if(!entity->next){
51  assert(0);
52  }
53  }
54 
55  return entity;
56 }
57 
58 //Root needs a special treating
59 static inline rofl_result_t __clone_root_monitored_entity(monitoring_state_t* monitoring, monitored_entity_t* root_dest, monitored_entity_t* root_orig){
60 
61  //First clone the contents
62  __clone_copy_me_fields(root_dest,root_orig);
63 
64  //Try to clone inner
65  if(root_orig->inner){
66  root_dest->inner = __clone_monitored_entity(root_orig->inner);
67  if(!root_dest->inner)
68  return ROFL_FAILURE;
69  }
70 
71  //Try to clone next
72  if(root_orig->next){
73  root_dest->next = __clone_monitored_entity(root_orig->next);
74  if(!root_dest->next){
75  if(root_dest->inner)
76  __monitoring_remove_monitored_entity(monitoring, root_dest->inner, true);
77  return ROFL_FAILURE;
78  }
79  }
80 
81  return ROFL_SUCCESS;
82 }
83 
84 //initialize in dynamic memory
86 
87  monitored_entity_t* entity;
88 
89  //We need to know really to place it
90  if( !monitoring || ( (prev && parent) || (!prev && !parent) ) ){
91  assert(0);
92  return NULL;
93  }
94 
95  //The root node is unique
96  if(prev && !prev->parent){
97  assert(0);
98  return NULL;
99  }
100 
101  //Entity
102  entity = platform_malloc_shared(sizeof(monitored_entity_t));
103 
104  if(!entity)
105  return NULL;
106 
107  //memset to zero
108  platform_memset(entity,0,sizeof(*entity));
109 
110  //Setting the type
111  entity->type = type;
112 
113  //Add it to the linked list
114  if(monitoring->rwlock)
115  platform_rwlock_wrlock(monitoring->rwlock);
116 
117  if(prev){
118  //Append it after the prev
119  entity->next = prev->next;
120  entity->prev = prev;
121  prev->next = entity;
122  entity->parent = prev->parent;
123  }else{
124  //Make it the first element of the inner leafs
125  if(parent->inner){
126  entity->next = parent->inner;
127  entity->next->prev = entity;
128  parent->inner = entity;
129  entity->parent = parent;
130  }else{
131  parent->inner = entity;
132  entity->parent = parent;
133  }
134  }
135 
136  //Increment rev counter
137  monitoring->last_rev++;
138 
139  if(monitoring->rwlock)
140  platform_rwlock_wrunlock(monitoring->rwlock);
141 
142  return entity;
143 }
144 
145 void __monitoring_dump_me(int indentation, monitored_entity_t* me);
146 
147 //destroy monitored entity
148 rofl_result_t __monitoring_remove_monitored_entity(monitoring_state_t* monitoring, monitored_entity_t* entity, bool lock_acquired){
149 
150  monitored_entity_t *inner_it, *next;
151 
152  if(!entity)
153  return ROFL_SUCCESS;
154 
155  //Sanity checks
156  if(!monitoring)
157  return ROFL_FAILURE;
158 
159  //Prevent readers (snapshot creators) to jump in
160  if(!lock_acquired && monitoring->rwlock)
161  platform_rwlock_wrlock(monitoring->rwlock);
162 
163 
164  //Delete (all) nested inner elements
165  inner_it = entity->inner;
166  while(inner_it){
167  next = inner_it->next;
168  __monitoring_remove_monitored_entity(monitoring, inner_it, true);
169  inner_it = next;
170  }
171 
172 
173  //Unlink from linked list
174  if(!entity->prev){
175  //Head of the list
176  if(entity->next)
177  entity->next->prev = NULL;
178  if(entity->parent)
179  entity->parent->inner = entity->next;
180  }else{
181  //Not the head of the list
182  if(entity->next)
183  entity->next->prev = entity->prev;
184  entity->prev->next = entity->next;
185  }
186 
187 
188  //Increment rev counter
189  monitoring->last_rev++;
190 
191  if(!lock_acquired && monitoring->rwlock)
192  platform_rwlock_wrunlock(monitoring->rwlock);
193 
194  //Free dynamic memory(only if it is not the root me)
195  if(entity != &monitoring->chassis){
196  platform_free_shared(entity);
197  }
198 
199  return ROFL_SUCCESS;
200 }
201 
202 //Cloning
203 
204 //
205 // Montoring elements
206 //
207 rofl_result_t __monitoring_init(monitoring_state_t* monitoring){
208 
209  //Clear all
210  platform_memset(monitoring,0,sizeof(*monitoring));
211 
212  //General flags
213  monitoring->last_rev = 1; //Must be one
214 
215  //Set primary monitored entity as being chassis
216  monitoring->chassis.type = ME_TYPE_CHASSIS;
217 
218  //Locking
219  monitoring->mutex = platform_mutex_init(NULL);
220  monitoring->rwlock = platform_rwlock_init(NULL);
221 
222  if(!monitoring->mutex || !monitoring->rwlock){
223  return ROFL_FAILURE;
224  }
225 
226  return ROFL_SUCCESS;
227 }
228 
229 //Destroys the monitoring state
230 void __monitoring_destroy(monitoring_state_t* monitoring){
231 
232  if(!monitoring)
233  return;
234 
235  //Lock rwlock (write)
236  if(monitoring->rwlock)
237  platform_rwlock_wrlock(monitoring->rwlock);
238 
239  //Destroy the inner-most monitored entity
240  __monitoring_remove_monitored_entity(monitoring, &monitoring->chassis, true);
241 
242  //Release dynamic memory allocated
243  if(monitoring->rwlock)
244  platform_rwlock_destroy(monitoring->rwlock);
245  if(monitoring->mutex)
246  platform_mutex_destroy(monitoring->mutex);
247 
248  if(monitoring->is_snapshot)
249  platform_free_shared(monitoring);
250 }
251 
252 void __monitoring_dump_me(int indentation, monitored_entity_t* me){
253 
254  int indentation_=indentation;
255 
256  if(!me)
257  return;
258 
259  for(;indentation_ > 0;indentation_--)
260  ROFL_PIPELINE_INFO_NO_PREFIX(" "); //Two space identation per level
261 
262  //Dump current node
263  ROFL_PIPELINE_INFO_NO_PREFIX("[" );
264  switch(me->type){
265  case ME_TYPE_OTHER:
266  ROFL_PIPELINE_INFO_NO_PREFIX("t-OTHER");
267  break;
268  case ME_TYPE_UNKNOWN:
269  ROFL_PIPELINE_INFO_NO_PREFIX("t-UNKNOWN");
270  break;
271  case ME_TYPE_CHASSIS:
272  ROFL_PIPELINE_INFO_NO_PREFIX("t-CHASSIS");
273  break;
274  case ME_TYPE_BACKPLANE:
275  ROFL_PIPELINE_INFO_NO_PREFIX("t-BACKPLANE");
276  break;
277  case ME_TYPE_CONTAINER:
278  ROFL_PIPELINE_INFO_NO_PREFIX("t-CONTAINER");
279  break;
280  case ME_TYPE_POWER_SUPPLY:
281  ROFL_PIPELINE_INFO_NO_PREFIX("t-POWER_SUPPLY");
282  break;
283  case ME_TYPE_FAN:
284  ROFL_PIPELINE_INFO_NO_PREFIX("t-FAN");
285  break;
286  case ME_TYPE_SENSOR:
287  ROFL_PIPELINE_INFO_NO_PREFIX("t-SENSOR");
288  break;
289  case ME_TYPE_MODULE:
290  ROFL_PIPELINE_INFO_NO_PREFIX("t-MODULE");
291  break;
292  case ME_TYPE_PORT:
293  ROFL_PIPELINE_INFO_NO_PREFIX("t-PORT");
294  break;
295  case ME_TYPE_STACK:
296  ROFL_PIPELINE_INFO_NO_PREFIX("t-STACK");
297  break;
298 
299  default:
300  assert(0);
301  break;
302  }
303 
304  ROFL_PIPELINE_INFO_NO_PREFIX(" (%p)] {name: %s}\n", me, me->name);
305 
306  //FIXME print sensor data
307 
308  //Dump inner
309  __monitoring_dump_me(indentation+1, me->inner);
310 
311  //Dump next element
312  __monitoring_dump_me(indentation, me->next);
313 }
314 
315 //Dump
317 
318  if(!monitoring)
319  return;
320 
321  if(monitoring->rwlock)
322  platform_rwlock_rdlock(monitoring->rwlock);
323 
324  ROFL_PIPELINE_INFO("\n"); //This is done in purpose
325  ROFL_PIPELINE_INFO("Dumping %smonitoring state(%p). Last rev: %"PRIu64"\n", monitoring->is_snapshot? "!SNAPSHOT! ":"", monitoring, monitoring->last_rev);
326 
327  //Dump chassis
328  __monitoring_dump_me(0, &monitoring->chassis);
329 
330  //Release the rdlock
331  if(monitoring->rwlock)
332  platform_rwlock_rdunlock(monitoring->rwlock);
333 
334  ROFL_PIPELINE_INFO_NO_PREFIX("\n\n"); //This is done in purpose
335 }
336 
337 
338 //
339 // Snapshots
340 //
341 
342 //Get a snapshot
344 
346 
348  if(!sn)
349  return NULL;
350 
351  //Lock rwlock (read)
352  if(monitoring->rwlock)
353  platform_rwlock_rdlock(monitoring->rwlock);
354 
355  //Copy the state
356  memcpy(sn, monitoring, sizeof(monitoring_state_t));
357 
358  //Set auxilary pointers to null
359  sn->mutex = sn->rwlock = NULL;
360 
361  //Clone monitored data
362  if(__clone_root_monitored_entity(monitoring, &sn->chassis, &monitoring->chassis) != ROFL_SUCCESS){
363  assert(0);
365  return NULL;
366  }
367 
368  //Release the rdlock
369  if(monitoring->rwlock)
370  platform_rwlock_rdunlock(monitoring->rwlock);
371 
372  //Mark as snapshot
373  sn->is_snapshot = true;
374 
375  return sn;
376 }
377 
378 //Update(inc atomically) the rev counter
379 void monitoring_state_inc_rev(monitoring_state_t* mon){
380  platform_atomic_inc64(&mon->last_rev, mon->mutex);
381 }
382 
Defines the locking interface used by the library. The user of the library MUST provide an implementa...
void platform_rwlock_rdlock(platform_rwlock_t *rwlock)
Performs a read-lock over the platform_rwlock_t mutex platform_mutex_init().
Defines the memory management interface used by the library. The user of the library MUST provide an ...
monitoring_snapshot_state_t * monitoring_get_snapshot(monitoring_state_t *monitoring)
Get a snapshot of the current monitoring state.
Definition: monitoring.c:343
void platform_rwlock_rdunlock(platform_rwlock_t *rwlock)
Performs a read-unlock over the platform_rwlock_t mutex platform_mutex_init().
Defines the atomic operations API, mostly atomic increments and addition operations.
void platform_rwlock_wrlock(platform_rwlock_t *rwlock)
Performs a write-lock over the platform_rwlock_t mutex platform_mutex_init().
Container of the monitoring state.
Definition: monitoring.h:168
ROFL_BEGIN_DECLS platform_mutex_t * platform_mutex_init(void *params)
Allocates and initializes a mutex.
void * platform_memset(void *src, int c, size_t length)
Sets 'c' to the whole chunk of memory.
void platform_rwlock_wrunlock(platform_rwlock_t *rwlock)
Performs a write-unlock over the platform_rwlock_t mutex platform_mutex_init().
platform_rwlock_t * platform_rwlock_init(void *params)
Allocates and initializes a rwlock.
ROFL_BEGIN_DECLS void platform_atomic_inc64(uint64_t *counter, platform_mutex_t *mutex)
Performs an atomic increment to the counter (64 bit type).
void platform_rwlock_destroy(platform_rwlock_t *rwlock)
Destroys and deallocates a rwlock previously inited by platform_rwlock_init().
void monitoring_dump(monitoring_state_t *monitoring)
Dumps the monitoring state, only meaningful for debugging purposes.
Definition: monitoring.c:316
void platform_mutex_destroy(platform_mutex_t *mutex)
Destroys and deallocates a mutex previously inited by platform_mutex_init().
Abstraction of a monitored entity data.
Definition: monitoring.h:124
monitored_entity_t * monitoring_add_monitored_entity(monitoring_state_t *monitoring, enum monitored_entity_type type, monitored_entity_t *prev, monitored_entity_t *parent)
Creates a monitored entity object and links it to the linked-list, in the position of prev OR parent...
Definition: monitoring.c:85
void * platform_malloc_shared(size_t length)
Allocates a chunk of dynamic memory of size length, which must be accessible (R/W) for all the thread...
monitored_entity_type
Monitoring entity type enum, defined according to RFC2737.
Definition: monitoring.h:98
ROFL_BEGIN_DECLS rofl_result_t __monitoring_init(monitoring_state_t *monitoring)
Initializes the monitoring state.
Definition: monitoring.c:207
void platform_free_shared(void *data)
Frees a chunk of dynamic memory previously allocated with platform_malloc_shared().
This file contains the abstractions to monitor particular elements of the platform, like sensors or other hardware state.