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
|