(file) Return to mgr.c CVS log (file) (dir) Up to [OMI] / omi / indication / indimgr

  1 krisbash 1.1 /*
  2              **==============================================================================
  3              **
  4              ** Open Management Infrastructure (OMI)
  5              **
  6              ** Copyright (c) Microsoft Corporation
  7              ** 
  8              ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
  9              ** use this file except in compliance with the License. You may obtain a copy 
 10              ** of the License at 
 11              **
 12              **     http://www.apache.org/licenses/LICENSE-2.0 
 13              **
 14              ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15              ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
 16              ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
 17              ** MERCHANTABLITY OR NON-INFRINGEMENT. 
 18              **
 19              ** See the Apache 2 License for the specific language governing permissions 
 20              ** and limitations under the License.
 21              **
 22 krisbash 1.1 **==============================================================================
 23              */
 24              
 25              #include "mgr.h"
 26              #include <pal/strings.h>
 27              #include <pal/format.h>
 28              #include <indication/common/indilog.h>
 29              #include <base/messages.h>
 30              #include <provreg/provreg.h>
 31              
 32              #define INDICATIONMGR_MAX_PAGES INFINITE
 33              
 34              /* Create indication manager */
 35              IndicationManager* IndiMgr_New(_In_ const IndicationHost* host)
 36              {
 37                  IndicationManager* mgr;
 38                  Batch *batch = Batch_New(INDICATIONMGR_MAX_PAGES);
 39                  DEBUG_ASSERT(host);
 40                  trace_FunctionEntered(__FILE__, __LINE__);
 41                  if (NULL == batch)
 42                  {
 43 krisbash 1.1         LOGD_BATCH_CREATE_OOM;
 44                      return NULL;
 45                  }
 46                  mgr = (IndicationManager*)Batch_GetClear(batch, sizeof(IndicationManager));
 47                  if (NULL == mgr)
 48                  {
 49                      LOGD_BATCH_OOM;
 50                      Batch_Delete(batch);
 51                      return NULL;
 52                  }
 53                  mgr->batch = batch;
 54                  memcpy(&mgr->base, host, sizeof(IndicationHost));
 55                  
 56                  ReadWriteLock_Init(&mgr->filterLock);
 57                  ReadWriteLock_Init(&mgr->listenerLock);
 58                  ReadWriteLock_Init(&mgr->subscripLock);
 59              
 60                  trace_IndiMgr_New( mgr );
 61              
 62                  return mgr;
 63              }
 64 krisbash 1.1 
 65              /* Create indication manager */
 66              _Use_decl_annotations_
 67              IndicationManager* IndiMgr_NewFromDisp(void* disp)
 68              {
 69                  IndicationHost host;
 70                  if (IndicationHost_InitFromDisp(disp, &host) != 0)
 71                  {
 72                      trace_IndiMgr_NewFromDispFailed(disp);
 73                      return NULL;
 74                  }
 75                  return IndiMgr_New(&host);
 76              }
 77              
 78              /* Delete indication manager */
 79              _Use_decl_annotations_
 80              int IndiMgr_Delete(IndicationManager* self)
 81              {
 82                  trace_IndiMgr_Delete(self);
 83                  DEBUG_ASSERT(self);
 84                  Batch_Delete(self->batch);
 85 krisbash 1.1     return 0;
 86              }
 87              
 88              /* Shutdown indication manager */
 89              _Use_decl_annotations_
 90              int IndiMgr_Shutdown(IndicationManager* self)
 91              {
 92                  trace_IndiMgr_Shutdown(self);
 93                  DEBUG_ASSERT(self);
 94              
 95                  /* TODO: Cancel active subscriptions */
 96                  /* Send subscription end to active clients */
 97              
 98                  /* cleanup subscriptions */
 99                  if (self->subscripList.head)
100                      CimBase_ReleaseList((CimBase*)self->subscripList.head);
101              
102                  /* cleanup filters */
103                  if (self->filterList.head)
104                      CimBase_ReleaseList((CimBase*)self->filterList.head);
105              
106 krisbash 1.1     /* cleanup listeners */
107                  if (self->listenerList.head)
108                      CimBase_ReleaseList((CimBase*)self->listenerList.head);
109              
110                  return IndiMgr_Delete(self);
111              }
112              
113              /*
114              **==============================================================================
115              **
116              ** Common helper functions
117              **
118              **==============================================================================
119              */
120              
121              /* Get object from list */
122              /* Caller need to make sure the approriate lock was taken on the linked list */
123              CimBase* _List_FindObjectByID(
124                  _In_ CimBase* head,
125                  _In_ CimBase* tail,
126                  _In_opt_z_ const MI_Char* id)
127 krisbash 1.1 {
128                  CimBase * target;
129                  if (id)
130                  {
131                      for (target = head; NULL != target; target = target->next)
132                      {
133                          const MI_Char* name = target->identifier;
134                          if (Tcscasecmp(name, id) == 0)
135                          {
136                              return target;
137                          }
138                      }
139                  }
140                  return NULL;
141              }
142              
143              /* Add object to list */
144              int _List_AddObject(
145                  _In_ CimBase** pphead,
146                  _In_ CimBase** pptail,
147                  _In_ CimBase* obj,
148 krisbash 1.1     _In_ void* container)
149              {
150                  CimBase * o = _List_FindObjectByID(*pphead, *pptail, obj->identifier);
151                  if (NULL != o)
152                  {
153                      trace_IndiMgr_ObjectExists(tcs(obj->identifier));
154                      return -1;
155                  }
156              
157                  List_Append((ListElem**)pphead,
158                      (ListElem**)pptail,
159                      (ListElem*)obj);
160              
161                  /* Add reference */
162                  obj->_ft->addref(obj);
163              
164                  /* Trigger OnAdd event */
165                  return obj->_ft->onadd(obj, container);
166              }
167              
168              /* Remove object from list by ID */
169 krisbash 1.1 int _List_RemoveObjectByID(
170                  _In_ CimBase** pphead,
171                  _In_ CimBase** pptail,
172                  _In_z_ const MI_Char* id,
173                  _In_ void* container)
174              {
175                  CimBase * o;
176                  DEBUG_ASSERT(id);
177                  o = _List_FindObjectByID(*pphead, *pptail, id);
178                  if (NULL == o)
179                  {
180                      trace_IndiMgr_CannotFindObject(tcs(id));
181                      return -1;
182                  }
183              
184                  List_Remove((ListElem**)pphead,
185                      (ListElem**)pptail,
186                      (ListElem*)o);
187              
188                  /* Release reference */
189                  o->_ft->release(o);
190 krisbash 1.1 
191                  /* Trigger OnRemove event */
192                  return o->_ft->onremove(o, container);
193              }
194              
195              /* Remove object from list */
196              int _List_RemoveObject(
197                  _In_ CimBase** pphead,
198                  _In_ CimBase** pptail,
199                  _In_ CimBase* obj,
200                  _In_ void* container)
201              {
202                  return _List_RemoveObjectByID(pphead, pptail, obj->identifier, container);
203              }
204              
205              /*
206              **==============================================================================
207              **
208              ** Common helper functions with ReadWriteLock
209              **
210              **==============================================================================
211 krisbash 1.1 */
212              CimBase* _LockListAndFindObjectByID(
213                  _In_ CimBase* head,
214                  _In_ CimBase* tail,
215                  _In_opt_z_ const MI_Char* id,
216                  _In_ ReadWriteLock* lock)
217              {
218                  CimBase* obj;
219                  ReadWriteLock_AcquireRead(lock);
220                  obj = _List_FindObjectByID(head, tail, id);
221                  ReadWriteLock_ReleaseRead(lock);
222                  return obj;
223              }
224              
225              /* Add object to list */
226              int _LockListAndAddObject(
227                  _In_ CimBase** pphead,
228                  _In_ CimBase** pptail,
229                  _In_ CimBase* obj,
230                  _In_ void* container,
231                  _In_ ReadWriteLock* lock)
232 krisbash 1.1 {
233                  int r;
234                  ReadWriteLock_AcquireWrite(lock);
235                  r = _List_AddObject(pphead, pptail, obj, container);
236                  ReadWriteLock_ReleaseWrite(lock);
237                  return r;
238              }
239              
240              /* Remove object from list by ID */
241              int _LockListAndRemoveObjectByID(
242                  _In_ CimBase** pphead,
243                  _In_ CimBase** pptail,
244                  _In_z_ const MI_Char* id,
245                  _In_ void* container,
246                  _In_ ReadWriteLock* lock)
247              {
248                  int r;
249                  ReadWriteLock_AcquireWrite(lock);
250                  r = _List_RemoveObjectByID(pphead, pptail, id, container);
251                  ReadWriteLock_ReleaseWrite(lock);
252                  return r;
253 krisbash 1.1 }
254              
255              /*
256              **==============================================================================
257              **
258              ** Filter management
259              **
260              **==============================================================================
261              */
262              /* Add filter to cache */
263              _Use_decl_annotations_
264              int IndiMgr_AddFilter(
265                  IndicationManager* self,
266                  FilterBase* filter)
267              {
268                  DEBUG_ASSERT(self);
269                  DEBUG_ASSERT(filter);
270                  trace_IndiMgr_AddFilter(self, filter);
271              
272                  /* Add filter to list */
273                  return _LockListAndAddObject(
274 krisbash 1.1         (CimBase**)&self->filterList.head,
275                      (CimBase**)&self->filterList.tail,
276                      (CimBase*)filter,
277                      self,
278                      &self->filterLock);
279              }
280              
281              /* Remove filter from cache */
282              _Use_decl_annotations_
283              int IndiMgr_RemoveFilter(
284                  IndicationManager* self,
285                  FilterBase* filter)
286              {
287                  DEBUG_ASSERT(self);
288                  DEBUG_ASSERT(filter);
289                  trace_IndiMgr_RemoveFilter(self, filter);
290                  if (filter->base._container != self)
291                  {
292                      trace_IndiMgr_FilterNotRemoved(filter, self);
293                      return -1;
294                  }
295 krisbash 1.1     
296                  return IndiMgr_RemoveFilterByName(self, filter->base.identifier);
297              }
298              
299              /* Remove filter from cache by name */
300              _Use_decl_annotations_
301              int IndiMgr_RemoveFilterByName(
302                  IndicationManager* self,
303                  const MI_Char* name)
304              {
305                  DEBUG_ASSERT(self);
306                  DEBUG_ASSERT(name);
307                  return _LockListAndRemoveObjectByID(
308                      (CimBase**)&self->filterList.head,
309                      (CimBase**)&self->filterList.tail,
310                      name,
311                      self,
312                      &self->filterLock);
313              }
314              
315              /* Find filter from cache, name (case insenstive) is the unique identifier of filter */
316 krisbash 1.1 _Use_decl_annotations_
317              FilterBase* IndiMgr_FindFilterByName(
318                  IndicationManager* self,
319                  const MI_Char *name)
320              {
321                  DEBUG_ASSERT(self);
322                  DEBUG_ASSERT(name);
323              
324                  return (FilterBase*)_LockListAndFindObjectByID(
325                      (CimBase*)self->filterList.head,
326                      (CimBase*)self->filterList.tail,
327                      name,
328                      &self->filterLock);
329              }
330              
331              
332              /*
333              **==============================================================================
334              **
335              ** Listener management
336              **
337 krisbash 1.1 **==============================================================================
338              */
339              
340              /* Add listener to cache */
341              _Use_decl_annotations_
342              int IndiMgr_AddListener(
343                  IndicationManager* self,
344                  Listener* listener)
345              {
346                  DEBUG_ASSERT(self);
347                  DEBUG_ASSERT(listener);
348                  trace_IndiMgr_AddListener(self, listener);
349              
350                  /* Add listener to list */
351                  return _LockListAndAddObject(
352                      (CimBase**)&self->listenerList.head,
353                      (CimBase**)&self->listenerList.tail,
354                      (CimBase*)listener,
355                      self,
356                      &self->listenerLock);
357              }
358 krisbash 1.1 
359              /* Remove listener from cache */
360              _Use_decl_annotations_
361              int IndiMgr_RemoveListener(
362                  IndicationManager* self,
363                  Listener* listener)
364              {
365                  DEBUG_ASSERT(self);
366                  DEBUG_ASSERT(listener);
367                  trace_IndiMgr_RemoveListener(self, listener);
368                  if (listener->base._container != self)
369                  {
370                      trace_IndiMgr_ListenerNotRemoved(listener, self);
371                      return -1;
372                  }
373                  return IndiMgr_RemoveListenerByName(self, listener->base.identifier);
374              }
375              
376              /* Remove Listener from cache by name */
377              _Use_decl_annotations_
378              int IndiMgr_RemoveListenerByName(
379 krisbash 1.1     IndicationManager* self,
380                  const MI_Char* name)
381              {
382                  DEBUG_ASSERT(self);
383                  DEBUG_ASSERT(name);
384                  return _LockListAndRemoveObjectByID(
385                      (CimBase**)&self->listenerList.head,
386                      (CimBase**)&self->listenerList.tail,
387                      name,
388                      self,
389                      &self->listenerLock);
390              }
391              
392              /* Find Listener from cache */
393              _Use_decl_annotations_
394              Listener* IndiMgr_FindListenerByName(
395                  IndicationManager* self,
396                  const MI_Char *name)
397              {
398                  DEBUG_ASSERT(self);
399                  DEBUG_ASSERT(name);
400 krisbash 1.1 
401                  return (Listener*)_LockListAndFindObjectByID(
402                      (CimBase*)self->listenerList.head,
403                      (CimBase*)self->listenerList.tail,
404                      name,
405                      &self->listenerLock);
406              }
407              
408              /*
409              **==============================================================================
410              **
411              ** Subscriptions management
412              **
413              **==============================================================================
414              */
415              /* Add subscription to cache */
416              /* Both filter and listener has to be present in cache already */
417              _Use_decl_annotations_
418              int IndiMgr_AddSubscription(
419                  IndicationManager* self,
420                  Subscription* subscrip)
421 krisbash 1.1 {
422                  DEBUG_ASSERT(self);
423                  DEBUG_ASSERT(subscrip);
424                  trace_IndiMgr_AddSubscription(self, subscrip);
425              
426                  /* Check the subscriptionID */
427                  DEBUG_ASSERT(subscrip->subscriptionID > 0);
428              
429                  /* Add listener to list */
430                  return _LockListAndAddObject(
431                      (CimBase**)&self->subscripList.head,
432                      (CimBase**)&self->subscripList.tail,
433                      (CimBase*)subscrip,
434                      self,
435                      &self->subscripLock);
436              }
437              
438              /* Remove subscription from cache */
439              _Use_decl_annotations_
440              int IndiMgr_RemoveSubscription(
441                  IndicationManager* self,
442 krisbash 1.1     Subscription* subscrip)
443              {
444                  DEBUG_ASSERT(self);
445                  DEBUG_ASSERT(subscrip);
446                  trace_IndiMgr_RemoveSubscription(self, subscrip);
447                  if (subscrip->base._container != self)
448                  {
449                      trace_IndiMgr_SubscriptionNotRemoved(subscrip, self);
450                      return -1;
451                  }
452                  return IndiMgr_RemoveSubscriptionByName(self, subscrip->base.identifier);
453              }
454              
455              /* Remove Subscription from cache by name */
456              _Use_decl_annotations_
457              int IndiMgr_RemoveSubscriptionByName(
458                  IndicationManager* self,
459                  const MI_Char* name)
460              {
461                  DEBUG_ASSERT(self);
462                  DEBUG_ASSERT(name);
463 krisbash 1.1 
464                  return _LockListAndRemoveObjectByID(
465                      (CimBase**)&self->subscripList.head,
466                      (CimBase**)&self->subscripList.tail,
467                      name,
468                      self,
469                      &self->subscripLock);
470              }
471              
472              /* Find subscription from cache */
473              _Use_decl_annotations_
474              Subscription* IndiMgr_FindSubscriptionByName(
475                  IndicationManager* self,
476                  const MI_Char *name)
477              {
478                  DEBUG_ASSERT(self);
479                  DEBUG_ASSERT(name);
480              
481                  return (Subscription*)_LockListAndFindObjectByID(
482                      (CimBase*)self->subscripList.head,
483                      (CimBase*)self->subscripList.tail,
484 krisbash 1.1         name,
485                      &self->subscripLock);
486              }
487              

ViewCVS 0.9.2