(file) Return to SubscriptionContext.c CVS log (file) (dir) Up to [OMI] / omi / provmgr

  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 <pal/format.h>
 26              #include <indication/common/indilog.h>
 27              #include "SubscriptionContext.h"
 28              #include "SubMgr.h"
 29              #include "filter.h"
 30              #include "context.h"
 31              #include "nioproc.h"
 32              #include <omi_error/errorutil.h>
 33              
 34              /*
 35               * Perform initialization of a SubscriptionContext object.
 36               */
 37              _Use_decl_annotations_
 38              MI_Result SubscrContext_Init(
 39                  SubscriptionContext* subCtx,
 40                  Provider* provider,
 41                  Context_Type type,    
 42                  InteractionOpenParams* interactionParams,
 43 krisbash 1.1     struct _SubMgrSubscription* subscription)
 44              {
 45                  MI_Result r;
 46                  if (!subCtx || !interactionParams || !interactionParams->msg || !subscription)
 47                  {
 48                      trace_SubscriptionContext_NullParameter();
 49                      return MI_RESULT_INVALID_PARAMETER;
 50                  }
 51              
 52                  DEBUG_ASSERT( CTX_TYPE_IND_SUBSCRIPTION == type || CTX_TYPE_IND_LIFECYCLE == type );
 53              
 54                  subCtx->subscription = subscription;
 55              
 56                  r = Context_Init_ByType( &subCtx->baseCtx, provider, interactionParams, type );
 57                  if ( MI_RESULT_OK != r )
 58                      subCtx->subscription = NULL;
 59                  else
 60                  {
 61                      /*
 62                       * Add refcount to subscription before calling into Subscribe,
 63                       * which means the provider owning one refcount to the subscription,
 64 krisbash 1.1          * the refcount will be released released within context.c:Context_PostMessageLeft
 65                       *
 66                       * Lifecycle contexts do not increment here because they do not call
 67                       * subscribe.
 68                       *
 69                       */
 70                       SubMgrSubscription_Addref(subCtx->subscription);
 71                  }
 72                  return r;
 73              }
 74              
 75              _Use_decl_annotations_
 76              void SubscrContext_Close( 
 77                  SubscriptionContext* subCtx )
 78              {
 79                  if (subCtx)
 80                  {
 81                      /* SubsriptionContext was allocated from the SubscribeReq Batch,
 82                       * so it will be freed when the message's batch is freed. */
 83                      subCtx->subscription = NULL;
 84                      Context_Close(&subCtx->baseCtx);
 85 krisbash 1.1     }
 86                  else
 87                      DEBUG_ASSERT(MI_FALSE); // Double free of Context / called on a NULL context
 88              }
 89              
 90              void _SendMessage(
 91                  _In_ Context* ctx,
 92                  _In_ Message* msgToSend )
 93              {
 94                  if (ctx->request->base.flags & WSMANFlag)
 95                  {
 96                      msgToSend->flags |= ctx->request->base.flags;
 97                  }
 98                  else /* Binary protocol */
 99                  {
100                      msgToSend->flags |= BinaryProtocolFlag;
101                  }
102              
103                  Context_PostMessageLeft( ctx, msgToSend );
104              }
105              
106 krisbash 1.1 /*
107               * Notifies the indication manager of a state change in a subscription.
108               */
109              _Use_decl_annotations_
110              MI_Result SubscrContext_SendFinalResultMsg(
111                  SubscriptionContext* subCtx,
112                  MI_Result result,
113                  const ZChar* errorMessage,
114                  const MI_Instance* cimError )
115              {
116                  Context* ctx = (Context*)subCtx;
117                  SubMgrSubscription* sub = subCtx->subscription;
118                  DEBUG_ASSERT( ctx && sub && ctx->request );
119              
120                  /* check if final message already sent or not */
121                  if ( MI_FALSE == SubMgrSubscription_ShouldSendFinalMsg(sub) )
122                      return MI_RESULT_FAILED;
123              
124                  trace_SubscrContext_SendFinalResultMsg( subCtx, result );
125              
126                  /* Send PostResultMsg Message */
127 krisbash 1.1     {
128                      PostResultMsg* resp;
129                      
130                      if (result == MI_RESULT_OK)
131                          resp = PostResultMsg_New( ctx->request->base.operationId );
132                      else
133                      {
134                          resp = PostResultMsg_NewAndSerialize(&ctx->request->base, cimError, errorMessage, MI_RESULT_TYPE_MI, result);
135                      }
136                      if (!resp)
137                      {
138                          return MI_RESULT_FAILED;
139                      }
140              
141                      _SendMessage( ctx, (Message*)resp );
142              
143                      trace_SubscrContext_SendFinalResultMsg_Sent(
144                          subCtx, result, resp, MessageName(resp->base.tag));
145              
146                      PostResultMsg_Release(resp);
147              
148 krisbash 1.1         if (ctx->result)
149                          *ctx->result = result;
150                  }
151                  return MI_RESULT_OK;
152              }
153              
154              _Use_decl_annotations_
155              MI_Result SubscrContext_SendSubscribeResponseMsg(
156                  SubscriptionContext* subCtx )
157              {
158                  Context* ctx = (Context*)subCtx;
159                  trace_SubscrContext_SendSubscribeResponseMsg( subCtx );
160              
161                  DEBUG_ASSERT( ctx->request );
162              
163                  /* Send SubscribeRes Message */
164                  {
165                      SubscribeRes* resp = SubscribeRes_New( ctx->request->base.operationId );
166                      if (!resp)
167                      {
168                          return MI_RESULT_FAILED;
169 krisbash 1.1         }
170              
171                      _SendMessage( ctx, (Message*)resp );
172              
173                      trace_SubscrContext_SendSubscribeResponseMsg_Sent(
174                          subCtx, resp, MessageName(resp->base.tag) );
175              
176                      SubscribeRes_Release(resp);
177              
178                      if (ctx->result)
179                          *ctx->result = MI_RESULT_OK;
180                  }
181                  return MI_RESULT_OK;
182              }
183              
184              SubMgrSubscription* SubscrContext_GetSubscription(
185                  _In_ SubscriptionContext* subCtx )
186              {
187                  return subCtx->subscription;
188              }
189              
190 krisbash 1.1 _Use_decl_annotations_
191              void SubscrContext_UnsubprvdOrSendfinalmsg(
192                  SubscriptionContext* subCtx,
193                  MI_Boolean invokeUnsubscribe,
194                  MI_Result finalResult)
195              {
196                  Provider* provider = subCtx->baseCtx.provider;
197                  SubMgrSubscription* subscription = subCtx->subscription;
198              
199                  trace_SubscrContext_UnsubprvdOrSendfinalmsgStart( subCtx, provider, subscription, invokeUnsubscribe );
200              
201                  if ( MI_TRUE == invokeUnsubscribe )
202                  {
203                      /*
204                       * Invoke Unsubscribe and get final result
205                       */
206                      Context ctx;
207                      MI_Result r = MI_RESULT_OK;
208                      Subunsub_Context_Init(&ctx, &r, subCtx->baseCtx.request);
209                      (*provider->classDecl->providerFT->Unsubscribe)(
210                          provider->self,
211 krisbash 1.1             &ctx.base,
212                          subscription->msg->nameSpace,
213                          subscription->msg->className,
214                          subscription->msg->subscriptionID,
215                          subCtx->subself);
216                      Context_Close(&ctx);
217                      finalResult = r;
218                  }
219              
220                  /*
221                   * PostResult to Unsubscribe context does not send final result message,
222                   * thus send final result message explicitly
223                   */
224                  MI_Context_PostResult ( &subCtx->baseCtx.base, finalResult );
225              
226                  trace_SubscrContext_UnsubprvdOrSendfinalmsgFinish( subCtx, provider, subscription, invokeUnsubscribe );
227              }
228              
229              _Use_decl_annotations_
230              MI_Result SubscrContext_Unsubscribe(
231                  SubscriptionContext* subCtx)
232 krisbash 1.1 {
233                  MI_Boolean invokeUnsubscribe = MI_FALSE;
234                  MI_Result result = MI_RESULT_OK;
235                  Provider* provider = subCtx->baseCtx.provider;
236                  SubMgrSubscription* subscription = subCtx->subscription;
237              
238                  trace_SubscrContext_Unsubscribe( subCtx, provider, subscription );
239              
240                  DEBUG_ASSERT(provider && subscription);
241                  DEBUG_ASSERT( (subCtx->baseCtx.ctxType == CTX_TYPE_IND_SUBSCRIPTION) ||
242                                (subCtx->baseCtx.ctxType == CTX_TYPE_IND_LIFECYCLE) );
243              
244                  if (subCtx->baseCtx.ctxType == CTX_TYPE_IND_LIFECYCLE)
245                  {
246                      goto DONE;
247                  }
248              
249                  if (subscription->state == SubscriptionState_Unsubscribing ||
250                      subscription->state == SubscriptionState_Unsubscribed)
251                  {
252                      trace_SubscrContext_AlreadyUnsubscribed( subscription );
253 krisbash 1.1         result = MI_RESULT_FAILED;
254                      goto DONE;
255                  }
256                  else if (SubscriptionState_Subscribed != subscription->state)
257                  {
258                      trace_SubscrState_InvalidForUnsubscribe(
259                          (int)subscription->state, tcs(subscription->msg->className));
260                      result = MI_RESULT_FAILED;
261                      goto DONE;
262                  }
263              
264                  DEBUG_ASSERT (provider->classDecl->providerFT &&
265                      provider->classDecl->providerFT->DisableIndications &&
266                      provider->classDecl->providerFT->Unsubscribe );
267              
268                  SubMgrSubscription_SetState(subscription, SubscriptionState_Unsubscribing);
269              
270                  if ( MI_FALSE == SubMgrSubscription_ShouldCallUnsubscribe(subscription) )
271                  {
272                      result = MI_RESULT_FAILED;
273                      goto DONE;
274 krisbash 1.1     }
275              
276                  /* Leave strand here due to provider could post result on same thread */
277                  /* Otherwise could cause deadlock */
278                  Strand_Leave(&subCtx->baseCtx.strand);
279              
280                  invokeUnsubscribe = MI_TRUE;
281              
282              DONE:
283                  /* There is only one IO thread in current process, */
284                  /* which has dead lock issue if have multi-thread (include IO thread) posting messages */
285                  /* simultaneously. To resolve the issue, unsubscribe has to be invoked from a separate thread */
286                  /* Upon implementing multi-thread IO for OMI server, this workaround should be removed */
287                  Schedule_UnsubscribeProvider( subCtx, invokeUnsubscribe, result );
288              
289                  trace_SubscrContext_UnsubscribeDone(subCtx, provider, subscription);
290                  return result;
291              }
292              

ViewCVS 0.9.2