|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @internalComponent |
|
19 */ |
|
20 |
|
21 #include <cflog.h> |
|
22 #include <rsshared.h> |
|
23 #include <commschan.h> |
|
24 #include <cfshared.h> |
|
25 #include <cfforwardmsg.h> |
|
26 using namespace CommsFW; |
|
27 #include "bm_defs.h" |
|
28 |
|
29 |
|
30 #ifdef _DEBUG |
|
31 // Panic category for "absolutely impossible!" vanilla ASSERT()-type panics from this module |
|
32 // (if it could happen through user error then you should give it an explicit, documented, category + code) |
|
33 _LIT(KSpecAssert_ElemRootServerbm, "ElemRootServerbm"); |
|
34 #endif |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 CPersistentSubModuleAddress::CPersistentSubModuleAddress(const TCFSubModuleAddress& aSubAddr,CPersistentSubModuleAddressCon* aContainerRef) : |
|
41 iSubAddr(aSubAddr), |
|
42 iContainerRef(aContainerRef), |
|
43 iAccessCount(1) |
|
44 // aContainerRef - the container that will store this object |
|
45 { |
|
46 } |
|
47 |
|
48 |
|
49 |
|
50 CPersistentSubModuleAddress* CPersistentSubModuleAddress::NewL(const TCFSubModuleAddress& aSubAddr, CPersistentSubModuleAddressCon* aContainerRef) |
|
51 { |
|
52 CPersistentSubModuleAddress* self = new (ELeave) CPersistentSubModuleAddress(aSubAddr,aContainerRef); |
|
53 return self; |
|
54 } |
|
55 |
|
56 |
|
57 void CPersistentSubModuleAddress::Close(TInt aIndex) |
|
58 // close a reference to this persistent sub module address |
|
59 // aIndex - if specified, Close will assume this element is at the specified index in the container |
|
60 // otherwise we need to find ourselves in the container. |
|
61 { |
|
62 --iAccessCount; |
|
63 __ASSERT_DEBUG(iAccessCount >= 0, User::Panic(KSpecAssert_ElemRootServerbm, 1)); |
|
64 if(iAccessCount == 0) |
|
65 { |
|
66 // remove |
|
67 if (aIndex >= 0) |
|
68 { |
|
69 // caller has already done work of finding which index |
|
70 iContainerRef->iPersistentModuleAddresses.Remove(aIndex); |
|
71 } |
|
72 else |
|
73 { |
|
74 TInt sessIdx = iContainerRef->iPersistentModuleAddresses.Find(this); |
|
75 if(sessIdx >= 0) |
|
76 { |
|
77 iContainerRef->iPersistentModuleAddresses.Remove(sessIdx); |
|
78 } |
|
79 } |
|
80 delete this; |
|
81 } |
|
82 } |
|
83 |
|
84 |
|
85 |
|
86 void CloseObject(TAny* aObject) |
|
87 /** |
|
88 * This method simply closes an object from the cleanup stack. The object must contain |
|
89 * a Close method. |
|
90 * |
|
91 * @param aObject - a TAny pointer to the object to close. |
|
92 * @return None |
|
93 */ |
|
94 { |
|
95 ((CPersistentSubModuleAddress*)aObject)->Close(); |
|
96 } |
|
97 |
|
98 |
|
99 |
|
100 CPersistentSubModuleAddressCon* CPersistentSubModuleAddressCon::NewL() |
|
101 { |
|
102 CPersistentSubModuleAddressCon* self = new (ELeave) CPersistentSubModuleAddressCon(); |
|
103 return self; |
|
104 } |
|
105 |
|
106 CPersistentSubModuleAddressCon::~CPersistentSubModuleAddressCon() |
|
107 { |
|
108 __ASSERT_DEBUG(iPersistentModuleAddresses.Count() == 0, User::Panic(KSpecAssert_ElemRootServerbm, 2)); |
|
109 iPersistentModuleAddresses.ResetAndDestroy(); |
|
110 } |
|
111 |
|
112 |
|
113 TCFSubModuleAddress& CPersistentSubModuleAddressCon::SetOrRetrieveNameLC(const TCFSubModuleAddress& aRef) |
|
114 // aRef - module address to add and return a reference to |
|
115 // pushes on the cleanup stack an operation to release this ref count object |
|
116 // returns - ref to the persistent module address created. Increments count on this module address. |
|
117 { |
|
118 // find name |
|
119 TInt countBack = iPersistentModuleAddresses.Count(); |
|
120 |
|
121 while (countBack > 0) |
|
122 { |
|
123 --countBack; |
|
124 |
|
125 CPersistentSubModuleAddress* modAddrRef = iPersistentModuleAddresses[countBack]; |
|
126 |
|
127 if (modAddrRef->SubAddrRef()==aRef) |
|
128 { |
|
129 modAddrRef->Open(); |
|
130 CleanupStack::PushL(TCleanupItem(CloseObject, modAddrRef)); |
|
131 return modAddrRef->SubAddrRef(); |
|
132 } |
|
133 } |
|
134 |
|
135 |
|
136 //not found so create copy of addr and add |
|
137 CPersistentSubModuleAddress* newModuleAddr; |
|
138 newModuleAddr = CPersistentSubModuleAddress::NewL(aRef,this); |
|
139 CleanupStack::PushL(newModuleAddr); |
|
140 #ifdef _DEBUG |
|
141 TInt ret = iPersistentModuleAddresses.Append(newModuleAddr); |
|
142 __ASSERT_DEBUG(ret!=KErrAlreadyExists, User::Panic(KSpecAssert_ElemRootServerbm, 3)); |
|
143 if (ret!=KErrNone) |
|
144 { |
|
145 User::Leave(ret); |
|
146 } |
|
147 #else |
|
148 iPersistentModuleAddresses.AppendL(newModuleAddr); |
|
149 #endif |
|
150 CleanupStack::Pop(newModuleAddr); |
|
151 CleanupStack::PushL(TCleanupItem(CloseObject, newModuleAddr)); |
|
152 return newModuleAddr->SubAddrRef(); |
|
153 |
|
154 } |
|
155 |
|
156 |
|
157 |
|
158 void CPersistentSubModuleAddressCon::Remove(const TCFSubModuleAddress& aRef) |
|
159 // panics in debug if not found |
|
160 { |
|
161 |
|
162 //find name |
|
163 TInt countBackIdx = iPersistentModuleAddresses.Count(); |
|
164 |
|
165 while (countBackIdx > 0) |
|
166 { |
|
167 --countBackIdx; |
|
168 if (iPersistentModuleAddresses[countBackIdx]->SubAddrRef()==aRef) |
|
169 { |
|
170 iPersistentModuleAddresses[countBackIdx]->Close(countBackIdx); |
|
171 return; |
|
172 } |
|
173 } |
|
174 __ASSERT_DEBUG(0, User::Panic(KSpecAssert_ElemRootServerbm, 4)); // we should never get a request to remove a non-existent element. In release, under releasing is tolerable (leak), over releasing might panic elsewhere (speculative) |
|
175 } |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 CBindManager* CBindManager::NewL(MRootServerNotify& aRootServerNotifier) |
|
181 /** Creates new CBindManager object. |
|
182 @param aRootServerNotifier Callback object when an unknown message is received |
|
183 @return Pointer to the CBindManager object |
|
184 @leave KErrNoMemory |
|
185 */ |
|
186 { |
|
187 __CFLOG(KLogSubSysRS, KLogCode, _L8("CBindManager::NewL")); |
|
188 CBindManager* pBm = new (ELeave) CBindManager(); |
|
189 pBm->iNotify = &aRootServerNotifier; |
|
190 |
|
191 CleanupStack::PushL(pBm); |
|
192 pBm->ConstructL(); |
|
193 CleanupStack::Pop(pBm); |
|
194 |
|
195 return pBm; |
|
196 } |
|
197 |
|
198 |
|
199 void CBindManager::ConstructL() |
|
200 { |
|
201 iModuleNameStor = CPersistentSubModuleAddressCon::NewL(); |
|
202 } |
|
203 |
|
204 |
|
205 CBindManager::~CBindManager() |
|
206 /** Destructor of CBindManager object. |
|
207 */ |
|
208 { |
|
209 TDblQueIter<CModule> moduleIter(iModuleList); |
|
210 CModule *pModule; |
|
211 while((pModule = moduleIter++) != NULL) |
|
212 { |
|
213 delete pModule; |
|
214 } |
|
215 |
|
216 TDblQueIter<CJob> jobIter(iJobList); |
|
217 CJob *pJob; |
|
218 while((pJob = jobIter++) != NULL) |
|
219 { |
|
220 delete pJob; |
|
221 } |
|
222 delete iModuleNameStor; |
|
223 |
|
224 TDblQueIter<CBindInfo> bindIter(iBindList); |
|
225 CBindInfo *pBind; |
|
226 while((pBind = bindIter++) != NULL) |
|
227 { |
|
228 delete pBind; |
|
229 } |
|
230 } |
|
231 |
|
232 void CBindManager::CreateModuleL(TRequestStatus& aStatus, |
|
233 const TCFModuleNameF& aModule, |
|
234 const RCFChannel::TMsgQueues& aInputQueues, |
|
235 const RCFChannel::TMsgQueues& aOutputQueues) |
|
236 /** Called by rootserver to inform the bindmanager of a new module and the queues |
|
237 to be used for communicating with it. The bindmanager will send a Discovery |
|
238 message to the module and will not complete the request until a valid |
|
239 DiscoveryResp is received or timeout occurs. |
|
240 @param aStatus status which will be completed when finished |
|
241 @param aModule name of module to create |
|
242 @param aInputQueues queues on which messages should sent to the module |
|
243 @param aOutputQueues queues on which messages will be received from the module |
|
244 @leave KErrNoMemory |
|
245 @leave ERSModuleAlreadyExist |
|
246 */ |
|
247 { |
|
248 // first check this module not already in my list |
|
249 TRAPD(ret, GetModulePtrL(aModule)); |
|
250 if (ret != KErrRSModuleUnknown) |
|
251 { |
|
252 __CFLOG_1(KLogSubSysRS, KLogCode, _L8("CBindManager::CreateModuleL - %S already exists"), &aModule); |
|
253 User::Leave(KErrRSModuleAlreadyExist); |
|
254 } |
|
255 |
|
256 // ok, so add it to my list |
|
257 CModule* pModule = CModule::NewL(this, aModule, iTransactionId, |
|
258 aInputQueues, aOutputQueues); |
|
259 CleanupStack::PushL(pModule); |
|
260 |
|
261 // now start a discovery request |
|
262 TUint taskId; |
|
263 pModule->DoDiscoverL(taskId); |
|
264 |
|
265 // and add the task to a job |
|
266 CJob *pJob = CJob::NewL(aStatus, this); |
|
267 CleanupStack::PushL(pJob); |
|
268 pJob->AddTaskL(taskId, pModule->Name()); |
|
269 CleanupStack::Pop(pJob); |
|
270 |
|
271 // now put module in list |
|
272 CleanupStack::Pop(pModule); |
|
273 iModuleList.AddLast(*pModule); |
|
274 |
|
275 // put job in main list and start its timer |
|
276 iJobList.AddLast(*pJob); |
|
277 pJob->StartTimeout(KJobTimeoutMicroseconds); |
|
278 } |
|
279 |
|
280 void CBindManager::SendL( const TCFModuleNameF& aModule, const RMessage2& aMessage ) |
|
281 { |
|
282 CModule* pModule = GetModulePtrL( aModule ); |
|
283 TCFForwardMsg forwardMsg(aMessage); |
|
284 pModule->SendL( forwardMsg ); |
|
285 } |
|
286 |
|
287 void CBindManager::UnbindAllModuleL(TRequestStatus& aStatus, |
|
288 const TCFModuleNameF& aModule, |
|
289 const TBool aModuleIsDead, |
|
290 CJob*& pJob) |
|
291 /** Send Unbind requests for every binding involving the specified module. If |
|
292 the ModuleIsDead parameter is true then no messages will be sent to the |
|
293 named target module. |
|
294 @param aStatus status which will be completed when finished |
|
295 @param aModule name of module to unbind |
|
296 @param aModuleIsDead indicates whether the target module is dead, and therefore |
|
297 should not be sent any messages |
|
298 @param pJob var parameter which will be set to point to a new job if one is |
|
299 created |
|
300 @leave KErrNoMemory |
|
301 @leave ERSModuleUnknown |
|
302 @leave ERSSubModuleUnknown |
|
303 @leave ERSBindingInProgress |
|
304 */ |
|
305 { |
|
306 // first validate that at least one binding exists and |
|
307 // all bindings can be unbound |
|
308 TBool bindingFound = EFalse; |
|
309 TDblQueIter<CBindInfo> bindIter(iBindList); |
|
310 CBindInfo *pBind; |
|
311 while((pBind = bindIter++) != NULL) |
|
312 { |
|
313 if (pBind->SubModuleAddr1().Module() == aModule || |
|
314 pBind->SubModuleAddr2().Module() == aModule) |
|
315 { |
|
316 bindingFound = ETrue; |
|
317 |
|
318 if (pBind->State1() == CBindManager::EBindInProgress || |
|
319 pBind->State2() == CBindManager::EBindInProgress) |
|
320 { |
|
321 User::Leave(KErrRSBindingInProgress); |
|
322 } |
|
323 } |
|
324 } |
|
325 |
|
326 if (!bindingFound) |
|
327 { |
|
328 // no tasks to perform so complete request and return immediately |
|
329 TRequestStatus *status = &aStatus; |
|
330 User::RequestComplete(status, KErrNone); |
|
331 pJob = 0; |
|
332 return; |
|
333 } |
|
334 |
|
335 // create a new job |
|
336 pJob = CJob::NewL(aStatus, this); |
|
337 CleanupStack::PushL(pJob); |
|
338 |
|
339 // now remove the bindings |
|
340 TBool tasksAdded = EFalse; |
|
341 bindIter.SetToFirst(); |
|
342 while((pBind = bindIter++) != NULL) |
|
343 { |
|
344 if (pBind->SubModuleAddr1().Module() != aModule && |
|
345 pBind->SubModuleAddr2().Module() != aModule) |
|
346 { |
|
347 // this binding not relevant |
|
348 continue; |
|
349 } |
|
350 |
|
351 // Bugfix: changed to ignore any binding to/from the module in question |
|
352 // if its state is >= EUnbindInProgress. Reasoning - this means that an unbind |
|
353 // has already been sent. Sending another can do no further good, and means we |
|
354 // have to cope with (legitimately) receiving multiple unbind responses. |
|
355 CBindManager::TBMBindState endpt1State = pBind->State1(); |
|
356 CBindManager::TBMBindState endpt2State = pBind->State2(); |
|
357 if(endpt1State == EUnbindInProgress || endpt2State == EUnbindInProgress) |
|
358 { |
|
359 continue; |
|
360 } |
|
361 TBool unbindModule1 = ETrue; |
|
362 if (endpt1State >= CBindManager::EUnbindInProgress || |
|
363 (pBind->SubModuleAddr1().Module() == aModule && aModuleIsDead)) |
|
364 { |
|
365 unbindModule1 = EFalse; |
|
366 pBind->SetState1(CBindManager::EUnbound); |
|
367 pBind->SetResult1(KErrNone); |
|
368 } |
|
369 |
|
370 TBool unbindModule2 = ETrue; |
|
371 if (endpt2State >= CBindManager::EUnbindInProgress || |
|
372 (pBind->SubModuleAddr2().Module() == aModule && aModuleIsDead)) |
|
373 { |
|
374 unbindModule2 = EFalse; |
|
375 pBind->SetState2(CBindManager::EUnbound); |
|
376 pBind->SetResult2(KErrNone); |
|
377 } |
|
378 |
|
379 if (!unbindModule1 && !unbindModule2) |
|
380 { |
|
381 // must be two binds within dead or not properly bound module - |
|
382 // nothing we can do but kill binding and look for next |
|
383 __CFLOG_3(KLogSubSysRS, KLogCode, _L8("CBindManager::UnbindAllModuleL() - deleting CBindInfo(%08x) - es1=%d, es2=%d"), pBind, endpt1State, endpt2State); |
|
384 delete pBind; |
|
385 continue; |
|
386 } |
|
387 |
|
388 CTask* pTask1 = 0; |
|
389 TBool newTask1 = EFalse; |
|
390 CModule* pModule1 = 0; |
|
391 if (unbindModule1) |
|
392 { |
|
393 pModule1 = GetModulePtrL(pBind->SubModuleAddr1()); |
|
394 const TCFSubModuleAddress& subModule1Ref1 = iModuleNameStor->SetOrRetrieveNameLC(pModule1->SubModuleNameRefL(pBind->SubModuleAddr1())); |
|
395 |
|
396 |
|
397 const TCFSubModuleAddress& subModule1Ref2 = iModuleNameStor->SetOrRetrieveNameLC(pModule1->SubModuleNameRefL(pBind->SubModuleAddr2())); |
|
398 |
|
399 |
|
400 newTask1 = pModule1->GetUnbindTaskL( |
|
401 subModule1Ref1, |
|
402 subModule1Ref2, |
|
403 aModuleIsDead, |
|
404 pTask1); |
|
405 if (newTask1) |
|
406 { |
|
407 CleanupStack::PushL(pTask1); |
|
408 } |
|
409 // coverity [leave_without_push] - existing tasks have already been allocated |
|
410 // and owned, therefore we don't need to push them onto the cleanup stack. |
|
411 pBind->SetState1(CBindManager::EUnbindInProgress); |
|
412 pJob->AddTaskL(pTask1->TaskId(), pBind->SubModuleAddr1().Module()); |
|
413 tasksAdded = ETrue; |
|
414 } |
|
415 |
|
416 CTask* pTask2 = 0; |
|
417 TBool newTask2 = EFalse; |
|
418 CModule* pModule2 = 0; |
|
419 if (unbindModule2) |
|
420 { |
|
421 pModule2 = GetModulePtrL(pBind->SubModuleAddr2()); |
|
422 //if we leave we will have this outstanding ref. Need to push onto cleanup stack until |
|
423 // we are clear of the "DoStartTaskL". |
|
424 |
|
425 const TCFSubModuleAddress& subModule2Ref1 = iModuleNameStor->SetOrRetrieveNameLC(pModule2->SubModuleNameRefL(pBind->SubModuleAddr1())); |
|
426 |
|
427 const TCFSubModuleAddress& subModule2Ref2 = iModuleNameStor->SetOrRetrieveNameLC(pModule2->SubModuleNameRefL(pBind->SubModuleAddr2())); |
|
428 |
|
429 |
|
430 newTask2 = pModule2->GetUnbindTaskL( |
|
431 subModule2Ref2, |
|
432 subModule2Ref1, |
|
433 aModuleIsDead, |
|
434 pTask2); |
|
435 if (newTask2) |
|
436 { |
|
437 CleanupStack::PushL(pTask2); |
|
438 } |
|
439 |
|
440 pBind->SetState2(CBindManager::EUnbindInProgress); |
|
441 // coverity [leave_without_push] - existing tasks have already been allocated |
|
442 // and owned, therefore we don't need to push them onto the cleanup stack. |
|
443 pJob->AddTaskL(pTask2->TaskId(), pBind->SubModuleAddr2().Module()); |
|
444 tasksAdded = ETrue; |
|
445 |
|
446 if (newTask2) |
|
447 { |
|
448 pModule2->DoStartTaskL(pTask2); |
|
449 CleanupStack::Pop(pTask2); |
|
450 CleanupStack::Pop(2); // moduleAddr refs from SetOrRetrieveNameLC calls |
|
451 } |
|
452 } |
|
453 |
|
454 if (newTask1) |
|
455 { |
|
456 __ASSERT_DEBUG(pModule1, User::Panic(KSpecAssert_ElemRootServerbm, 5)); // LINT is skeptical |
|
457 pModule1->DoStartTaskL(pTask1); |
|
458 CleanupStack::Pop(pTask1); |
|
459 CleanupStack::Pop(2); // moduleAddr refs from SetOrRetrieveNameLC calls |
|
460 } |
|
461 |
|
462 } // end while |
|
463 |
|
464 if (tasksAdded) |
|
465 { |
|
466 iJobList.AddLast(*pJob); |
|
467 pJob->StartTimeout(KJobTimeoutMicroseconds); |
|
468 CleanupStack::Pop(pJob); |
|
469 } |
|
470 else |
|
471 { |
|
472 // no tasks to perform so complete request immediately |
|
473 TRequestStatus *status = &aStatus; |
|
474 User::RequestComplete(status, KErrNone); |
|
475 |
|
476 CleanupStack::PopAndDestroy(pJob); |
|
477 pJob = 0; |
|
478 } |
|
479 } |
|
480 |
|
481 |
|
482 void CBindManager::ConvertRSBindType(const TRSBindType aType, |
|
483 TCFBindType& aUpperBindType, |
|
484 TCFBindType& aLowerBindType) |
|
485 /** Convert a rootserver style binding type to the equivalent comms framework |
|
486 type |
|
487 @param aType a RootServer binding type |
|
488 @param aUpperBindType comms framework bind type for upper submodule |
|
489 @param aLowerBindType comms framework bind type for lower submodule |
|
490 */ |
|
491 { |
|
492 switch(aType) |
|
493 { |
|
494 case EHierarchical: |
|
495 aUpperBindType = EHierarchicalUpper; |
|
496 aLowerBindType = EHierarchicalLower; |
|
497 break; |
|
498 case ECustom: |
|
499 aUpperBindType = EHorizontal; |
|
500 aLowerBindType = EHorizontal; |
|
501 break; |
|
502 default: |
|
503 aUpperBindType = EOther; |
|
504 aLowerBindType = EOther; |
|
505 break; |
|
506 } |
|
507 } |
|
508 |
|
509 CBindInfo* CBindManager::FindBindInfo(const TCFSubModuleAddress& aUpperSubmodule, |
|
510 const TCFSubModuleAddress& aLowerSubmodule) |
|
511 /** If a bind exists between the two specified modules, then return a pointer to |
|
512 it. |
|
513 @param aUpperSubmodule the upper module in the bindinfo |
|
514 @param aLowerSubmodule the lower module in the bindinfo |
|
515 @return Ptr to a matching bindinfo or 0 is none found |
|
516 */ |
|
517 { |
|
518 TDblQueIter<CBindInfo> bindIter(iBindList); |
|
519 CBindInfo* pBind = 0; |
|
520 while((pBind = bindIter++) != NULL) |
|
521 { |
|
522 // Bugfix; there's one bindinfo for two mirror-imaged requests, hence need to test both possibilities |
|
523 if((pBind->SubModuleAddr1() == aUpperSubmodule && pBind->SubModuleAddr2() == aLowerSubmodule) || |
|
524 (pBind->SubModuleAddr2() == aUpperSubmodule && pBind->SubModuleAddr1() == aLowerSubmodule)) |
|
525 { |
|
526 break; |
|
527 } |
|
528 } |
|
529 return pBind; |
|
530 } |
|
531 |
|
532 void CBindManager::BindSubmodulesL(TRequestStatus& aStatus, |
|
533 const TRSBindType aType, |
|
534 const TCFSubModuleAddress& aUpperSubmodule, |
|
535 const TCFSubModuleAddress& aLowerSubmodule, |
|
536 TInt aForwardQLength, |
|
537 TInt aReverseQLength) |
|
538 /** Called by rootserver to bind two submodules. If the request is valid the |
|
539 bindmanager will send a Bind message to the module associated with each |
|
540 submodule (which may be the same for both) and will complete the request |
|
541 when a valid response is received from both, or timeout occurs. |
|
542 If a cancelled bind request exists for the same modules and type, then it |
|
543 is reactivated with the new aStatus. |
|
544 @param aStatus status which will be completed when finished |
|
545 @param aType type of binding defined by rootserver |
|
546 @param aUpperSubmodule first submodule to bind - the upper module in |
|
547 hierarchical bindings |
|
548 @param aLowerSubmodule second submodule to bind |
|
549 @param aForwardQLength xxx |
|
550 @param aReverseQLength xx |
|
551 @leave KErrNoMemory |
|
552 @leave ERSModuleUnknown |
|
553 @leave ERSSubModuleUnknown |
|
554 @leave ERSModuleNotReady |
|
555 @leave ERSAlreadyBound |
|
556 @leave ERSBindingInProgress |
|
557 */ |
|
558 { |
|
559 // check modules exist and are ready for binding |
|
560 CModule* pUpperModule = GetModulePtrL(aUpperSubmodule); |
|
561 CModule* pLowerModule = GetModulePtrL(aLowerSubmodule); |
|
562 if (pUpperModule->Initialising() || |
|
563 pLowerModule->Initialising()) |
|
564 { |
|
565 User::Leave(KErrRSModuleNotReady); |
|
566 } |
|
567 |
|
568 // see if binding already exists and if so can be tried again |
|
569 CBindInfo *pBind = FindBindInfo(aUpperSubmodule, aLowerSubmodule); |
|
570 TBool bindExists = (pBind != 0); |
|
571 if (bindExists) |
|
572 { |
|
573 if (pBind->State1() == CBindManager::EBound && |
|
574 pBind->State2() == CBindManager::EBound) |
|
575 { |
|
576 User::Leave(KErrRSAlreadyBound); |
|
577 } |
|
578 if (pBind->State1() == CBindManager::EBindInProgress || |
|
579 pBind->State2() == CBindManager::EBindInProgress) |
|
580 { |
|
581 User::Leave(KErrRSBindingInProgress); |
|
582 } |
|
583 } |
|
584 else |
|
585 { |
|
586 // create a bind object - note this also creates the channels |
|
587 pBind = CBindInfo::NewL(aType, |
|
588 pUpperModule->SubModuleNameRefL(aUpperSubmodule), |
|
589 pLowerModule->SubModuleNameRefL(aLowerSubmodule), |
|
590 aForwardQLength,aReverseQLength); |
|
591 CleanupStack::PushL(pBind); |
|
592 pBind->SetState1(CBindManager::EBindInProgress); |
|
593 pBind->SetState2(CBindManager::EBindInProgress); |
|
594 } |
|
595 |
|
596 TCFBindType upperBindType; |
|
597 TCFBindType lowerBindType; |
|
598 ConvertRSBindType(aType, upperBindType, lowerBindType); |
|
599 |
|
600 RCFChannel::TMsgQueues queues1; |
|
601 pBind->Channel1().GetMsgQueues(queues1); |
|
602 RCFChannel::TMsgQueues queues2; |
|
603 pBind->Channel2().GetMsgQueues(queues2); |
|
604 |
|
605 // create a job and add to the list |
|
606 CJob *pJob = CJob::NewL(aStatus, this); |
|
607 CleanupStack::PushL(pJob); |
|
608 |
|
609 // get modules to create tasks or return existing ones check the bind |
|
610 // state in case an identical job was cancelled but one task was |
|
611 // finished, ie the task doesn't exist any more, but we don't want to |
|
612 // send another - if it ended in error then we will send another |
|
613 CTask* pLowerTask = 0; |
|
614 TBool newLowerTask = EFalse; |
|
615 if (pBind->State2() != CBindManager::EBound) |
|
616 { |
|
617 const TCFSubModuleAddress& state2LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule)); |
|
618 |
|
619 const TCFSubModuleAddress& state2UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule)); |
|
620 |
|
621 newLowerTask = pLowerModule->GetBindTaskL(queues2, queues1, |
|
622 state2LowerSubModuleRef, |
|
623 state2UpperSubModuleRef, |
|
624 lowerBindType, |
|
625 pLowerTask); |
|
626 if (newLowerTask) |
|
627 { |
|
628 CleanupStack::PushL(pLowerTask); |
|
629 } |
|
630 // coverity [leave_without_push] - existing tasks have already been allocated |
|
631 // and owned, therefore we don't need to push them onto the cleanup stack. |
|
632 pJob->AddTaskL(pLowerTask->TaskId(), aLowerSubmodule.Module()); |
|
633 } |
|
634 |
|
635 CTask* pUpperTask = 0; |
|
636 TBool newUpperTask = EFalse; |
|
637 if (pBind->State1() != CBindManager::EBound) |
|
638 { |
|
639 const TCFSubModuleAddress& state1UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule)); |
|
640 |
|
641 const TCFSubModuleAddress& state1LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule)); |
|
642 |
|
643 newUpperTask = pUpperModule->GetBindTaskL(queues1, queues2, |
|
644 state1UpperSubModuleRef, |
|
645 state1LowerSubModuleRef, |
|
646 upperBindType, |
|
647 pUpperTask); |
|
648 if (newUpperTask) |
|
649 { |
|
650 CleanupStack::PushL(pUpperTask); |
|
651 } |
|
652 // coverity [leave_without_push] - existing tasks have already been allocated |
|
653 // and owned, therefore we don't need to push them onto the cleanup stack. |
|
654 pJob->AddTaskL(pUpperTask->TaskId(), aUpperSubmodule.Module()); |
|
655 } |
|
656 |
|
657 // Check that both messages can be sent before trying anything |
|
658 User::LeaveIfError(pUpperModule->ReserveSpaceInSendQueue()); |
|
659 User::LeaveIfError(pLowerModule->ReserveSpaceInSendQueue()); |
|
660 |
|
661 // now we can actually send messages |
|
662 if (newUpperTask) |
|
663 { |
|
664 pUpperModule->DoStartTaskL(pUpperTask); |
|
665 CleanupStack::Pop(pUpperTask); |
|
666 CleanupStack::Pop(2); // upper and lower SubModuleObj from moduleAddr SetOrRetrieveNameLC calls |
|
667 } |
|
668 |
|
669 if (newLowerTask) |
|
670 { |
|
671 pLowerModule->DoStartTaskL(pLowerTask); |
|
672 CleanupStack::Pop(pLowerTask); |
|
673 CleanupStack::Pop(2); // upper and lower SubModuleObj from moduleAddr SetOrRetrieveNameLC calls |
|
674 } |
|
675 |
|
676 CleanupStack::Pop(pJob); |
|
677 iJobList.AddLast(*pJob); |
|
678 pJob->StartTimeout(KJobTimeoutMicroseconds); |
|
679 |
|
680 if (!bindExists) |
|
681 { |
|
682 CleanupStack::Pop(pBind); |
|
683 iBindList.AddLast(*pBind); |
|
684 } |
|
685 } |
|
686 |
|
687 void CBindManager::UnbindSubmodulesL(TRequestStatus& aStatus, |
|
688 const TCFSubModuleAddress& aUpperSubmodule, |
|
689 const TCFSubModuleAddress& aLowerSubmodule) |
|
690 /** Called by rootserver to unbind two submodules. If the request is valid the |
|
691 bindmanager will send an Unbind message to the module associated with each |
|
692 submodule (which may be the same for both) and will complete the request |
|
693 when a valid response is received from both, or timeout occurs. |
|
694 @param aStatus status which will be completed when finished |
|
695 @param aUpperSubmodule first submodule to unbind |
|
696 @param aLowerSubmodule second submodule to unbind |
|
697 @leave KErrNoMemory |
|
698 @leave ERSBindingUnknown |
|
699 @leave ERSModuleUnknown |
|
700 @leave ERSSubModuleUnknown |
|
701 @leave ERSBindingInProgress |
|
702 */ |
|
703 { |
|
704 // check binding exists and is in a suitable state for unbinding |
|
705 CBindInfo *pBind = FindBindInfo(aUpperSubmodule, aLowerSubmodule); |
|
706 if (!pBind) |
|
707 { |
|
708 User::Leave(KErrRSBindingUnknown); |
|
709 } |
|
710 else if (pBind->State1() == CBindManager::EBindInProgress || |
|
711 pBind->State2() == CBindManager::EBindInProgress) |
|
712 { |
|
713 User::Leave(KErrRSBindingInProgress); |
|
714 } |
|
715 |
|
716 // check modules exist |
|
717 CModule* pUpperModule = GetModulePtrL(aUpperSubmodule); |
|
718 CModule* pLowerModule = GetModulePtrL(aLowerSubmodule); |
|
719 |
|
720 // create a new job and add to list |
|
721 CJob* pJob = CJob::NewL(aStatus, this); |
|
722 CleanupStack::PushL(pJob); |
|
723 |
|
724 // get modules to create tasks or return existing ones check the bind |
|
725 // state in case an identical job was cancelled but one task was |
|
726 // finished, ie the task doesn't exist any more, but we don't want to |
|
727 // send another - if it ended in error then we will send another |
|
728 CTask* pLowerTask = 0; |
|
729 TBool newLowerTask = EFalse; |
|
730 if (pBind->State2() != CBindManager::EUnbound) |
|
731 { |
|
732 const TCFSubModuleAddress& state2LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule)); |
|
733 |
|
734 const TCFSubModuleAddress& state2UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule)); |
|
735 |
|
736 newLowerTask = pLowerModule->GetUnbindTaskL( |
|
737 state2LowerSubModuleRef, |
|
738 state2UpperSubModuleRef, |
|
739 EFalse, |
|
740 pLowerTask); |
|
741 if (newLowerTask) |
|
742 { |
|
743 CleanupStack::PushL(pLowerTask); |
|
744 } |
|
745 // coverity [leave_without_push] - existing tasks have already been allocated |
|
746 // and owned, therefore we don't need to push them onto the cleanup stack. |
|
747 pBind->SetState2(CBindManager::EUnbindInProgress); |
|
748 pJob->AddTaskL(pLowerTask->TaskId(), aLowerSubmodule.Module()); |
|
749 } |
|
750 |
|
751 CTask* pUpperTask = 0; |
|
752 TBool newUpperTask = EFalse; |
|
753 if (pBind->State1() != CBindManager::EUnbound) |
|
754 { |
|
755 const TCFSubModuleAddress& state1UpperSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pUpperModule->SubModuleNameRefL(aUpperSubmodule)); |
|
756 |
|
757 const TCFSubModuleAddress& state1LowerSubModuleRef = iModuleNameStor->SetOrRetrieveNameLC(pLowerModule->SubModuleNameRefL(aLowerSubmodule)); |
|
758 newUpperTask = pUpperModule->GetUnbindTaskL( |
|
759 state1UpperSubModuleRef, |
|
760 state1LowerSubModuleRef, |
|
761 EFalse, |
|
762 pUpperTask); |
|
763 if (newUpperTask) |
|
764 { |
|
765 CleanupStack::PushL(pUpperTask); |
|
766 } |
|
767 // coverity [leave_without_push] - existing tasks have already been allocated |
|
768 // and owned, therefore we don't need to push them onto the cleanup stack. |
|
769 pBind->SetState1(CBindManager::EUnbindInProgress); |
|
770 pJob->AddTaskL(pUpperTask->TaskId(), aUpperSubmodule.Module()); |
|
771 } |
|
772 |
|
773 // Check that both messages can be sent before trying anything |
|
774 User::LeaveIfError(pUpperModule->ReserveSpaceInSendQueue()); |
|
775 User::LeaveIfError(pLowerModule->ReserveSpaceInSendQueue()); |
|
776 |
|
777 // now we can actually send messages |
|
778 if (newUpperTask) |
|
779 { |
|
780 pUpperModule->DoStartTaskL(pUpperTask); |
|
781 CleanupStack::Pop(pUpperTask); |
|
782 CleanupStack::Pop(2); // upper and lower SubModuleObj |
|
783 } |
|
784 |
|
785 if (newLowerTask) |
|
786 { |
|
787 pLowerModule->DoStartTaskL(pLowerTask); |
|
788 CleanupStack::Pop(pLowerTask); |
|
789 CleanupStack::Pop(2); // upper and lower SubModuleObj |
|
790 } |
|
791 |
|
792 CleanupStack::Pop(pJob); |
|
793 iJobList.AddLast(*pJob); |
|
794 pJob->StartTimeout(KJobTimeoutMicroseconds); |
|
795 } |
|
796 |
|
797 |
|
798 |
|
799 void CBindManager::UnbindAlreadyDeadL(TRequestStatus& aStatus, |
|
800 const TCFModuleNameF& aModule) |
|
801 /** Called by rootserver to unbind all submodules from a specific module where |
|
802 the module is known to be dead. The bindmanager will send Unbind unbind |
|
803 messages for each existing binding, except when the destination is the dead |
|
804 module. The request will complete when a valid response is received for each |
|
805 message or timeout occurs. |
|
806 @param aStatus status which will be completed when finished |
|
807 @param aModule dead module to unbind |
|
808 @leave KErrNoMemory |
|
809 @leave ERSModuleUnknown |
|
810 @leave ERSBindingInProgress |
|
811 */ |
|
812 { |
|
813 CJob *pJob; |
|
814 UnbindAllModuleL(aStatus, aModule, ETrue, pJob); |
|
815 } |
|
816 |
|
817 TInt CBindManager::EnumerateBindings(const TCFSubModuleAddress& aSubModule, TBool aRestart, TBindingInfo& aInfo) |
|
818 /** Enumerates bindings by returning one at a time until there is no more. |
|
819 @param aSubModule submodule or module to count bindings for |
|
820 @param aRestart whether to start from the beginning |
|
821 @param aInfo reference to a binding info |
|
822 */ |
|
823 { |
|
824 // for each bindinfo, if a module matches then add it to aInfo |
|
825 TDblQueIter<CBindInfo> bindIter(iBindList); |
|
826 CBindInfo *pBind; |
|
827 |
|
828 TInt res = KErrEof; |
|
829 |
|
830 if(aRestart) |
|
831 { |
|
832 iEnumBindingsIdx=0; |
|
833 } |
|
834 |
|
835 TInt count=0; |
|
836 // while [not found] && [there is a next] |
|
837 while( (KErrNone!=res) && ((pBind = bindIter++) != NULL) ) |
|
838 { |
|
839 // if one of the <module:submodule> addressess have an eact match |
|
840 // OR we don't specify a submodule and then have a match on module level only. |
|
841 if ( pBind->SubModuleAddr1() == aSubModule || |
|
842 pBind->SubModuleAddr2() == aSubModule || |
|
843 ( 0==aSubModule.SubModule().Length() && |
|
844 (pBind->SubModuleAddr1().Module() == aSubModule.Module() || |
|
845 pBind->SubModuleAddr2().Module() == aSubModule.Module()))) |
|
846 { |
|
847 |
|
848 // If at extraction-point |
|
849 if(count==iEnumBindingsIdx) |
|
850 { |
|
851 aInfo.iType = pBind->BindType(); |
|
852 aInfo.iSubModuleAddr1 = pBind->SubModuleAddr1(); |
|
853 aInfo.iSubModuleAddr2 = pBind->SubModuleAddr2(); |
|
854 aInfo.iSubModuleState1 = pBind->State1(); |
|
855 aInfo.iSubModuleState2 = pBind->State2(); |
|
856 aInfo.iSubModuleResult1 = pBind->Result1(); |
|
857 aInfo.iSubModuleResult2 = pBind->Result2(); |
|
858 res = KErrNone; // It was found, end loop and return KErrNone |
|
859 ++iEnumBindingsIdx; |
|
860 } |
|
861 ++count; |
|
862 } |
|
863 } |
|
864 return res; |
|
865 } |
|
866 |
|
867 |
|
868 void CBindManager::UnbindAllAndShutDownL(TRequestStatus& aStatus, |
|
869 const TCFModuleNameF& aModule, TCFShutdownType aType) |
|
870 /** Called by rootserver to unbind all submodules from a specific module and then |
|
871 send a shutdown message. |
|
872 The bindmanager will send a pair of Unbind messages for each existing binding |
|
873 followed by a shutdown only to the module specified. The request will complete |
|
874 when a valid response is received for each message or timeout occurs. |
|
875 @param aStatus status which will be completed when finished |
|
876 @param aModule module to unbind and shut down |
|
877 @param aType xx |
|
878 @leave KErrNoMemory |
|
879 @leave ERSModuleUnknown |
|
880 @leave ERSModuleNotReady |
|
881 @leave ERSBindingInProgress |
|
882 */ |
|
883 { |
|
884 // can't do this if we have an outstanding discovery request |
|
885 CModule *pModule = GetModulePtrL(aModule); |
|
886 if (pModule->Initialising()) |
|
887 { |
|
888 User::Leave(KErrRSModuleNotReady); |
|
889 } |
|
890 |
|
891 CJob *pJob; |
|
892 UnbindAllModuleL(aStatus, aModule, EFalse, pJob); |
|
893 |
|
894 // send the shutdown request |
|
895 TCFShutdownMsg shutDownMsg(aType); |
|
896 pModule->SendL(shutDownMsg); |
|
897 |
|
898 } |
|
899 |
|
900 void CBindManager::ModuleEndedL(const TCFModuleNameF& aModule) |
|
901 /** Called by rootserver to indicate that a module thread has exited and therefore |
|
902 any information stored about it should be deleted. |
|
903 @param aModule module to end |
|
904 @leave KErrNoMemory |
|
905 @leave ERSModuleUnknown |
|
906 @leave ERSBindingExists indicates that a binding still exists for the module |
|
907 and should be removed by calling UnbindAlreadyDeadL to avoid an inconsistent |
|
908 state in module to which it is bound |
|
909 */ |
|
910 { |
|
911 __CFLOG_1(KLogSubSysRS, KLogCode, _L8("CBindManager::ModuleEndedL - %S ended"), &aModule); |
|
912 |
|
913 CModule* pModule = GetModulePtrL(aModule); |
|
914 |
|
915 TInt leaveCode = KErrNone; |
|
916 TDblQueIter<CBindInfo> bindIter(iBindList); |
|
917 CBindInfo *pBind; |
|
918 pModule->EndAllTasks( KErrCancel ); |
|
919 |
|
920 while((pBind = bindIter++) != NULL) |
|
921 { |
|
922 TBool firstModOfBinding = pBind->SubModuleAddr1().Module() == aModule; |
|
923 TBool secondModOfBinding = pBind->SubModuleAddr2().Module() == aModule; |
|
924 |
|
925 if(firstModOfBinding) |
|
926 { |
|
927 pBind->SetState1(CBindManager::EUnbound); |
|
928 if(pBind->State2() >= CBindManager::EUnbindError) |
|
929 { |
|
930 delete pBind; |
|
931 } |
|
932 } |
|
933 else if(secondModOfBinding) |
|
934 { |
|
935 pBind->SetState2(CBindManager::EUnbound); |
|
936 if(pBind->State1() >= CBindManager::EUnbindError) |
|
937 { |
|
938 delete pBind; |
|
939 } |
|
940 } |
|
941 } |
|
942 |
|
943 // if any valid and current bindings still exist then deleting the module |
|
944 // will mess up our state - so leave now |
|
945 User::LeaveIfError(leaveCode); |
|
946 delete pModule; |
|
947 } |
|
948 |
|
949 TInt CBindManager::Cancel(TRequestStatus& aStatus) |
|
950 /** Called by rootserver to cancel the request with the specified TRequestStatus. |
|
951 The bindmanager will continue to process responses from the modules and |
|
952 update the internal state information accordingly. |
|
953 @param aStatus status to be cancelled |
|
954 @return KErrNoMemory |
|
955 @return ERSStatusUnknown |
|
956 */ |
|
957 { |
|
958 // find job and mark it as cancelled |
|
959 TDblQueIter<CJob> jobIter(iJobList); |
|
960 CJob *pJob; |
|
961 TInt ret = KErrRSStatusUnknown; |
|
962 while((pJob = jobIter++) != NULL) |
|
963 { |
|
964 if (pJob->HasStatus(aStatus)) |
|
965 { |
|
966 pJob->Cancel(); |
|
967 ret = KErrNone; |
|
968 break; |
|
969 } |
|
970 } |
|
971 return ret; |
|
972 } |
|
973 |
|
974 |
|
975 TInt CBindManager::EnumerateSubModules(const TCFModuleNameF& aModuleName, TInt aPosition, TCFSubModuleNameF& aSubModuleName) |
|
976 /** Return a list of sub modules, starting at the point specified by aFrom |
|
977 @param aModuleName The module to enumerate submodules from |
|
978 @param aPosition Start writing submodules names from here |
|
979 @param aSubModuleName The descriptor to write to |
|
980 @return an error code if module not found |
|
981 */ |
|
982 { |
|
983 CModule* module = NULL; |
|
984 // check module/submodule exists |
|
985 TRAPD(ret, module = GetModulePtrL(aModuleName);) |
|
986 if (KErrNone != ret) |
|
987 { |
|
988 return ret; |
|
989 } |
|
990 return module->EnumerateSubModules( aPosition, aSubModuleName ); |
|
991 } |
|
992 |
|
993 TInt CBindManager::NumSubModules( const TCFModuleNameF& aName, TInt& aNumSubs ) |
|
994 /** Return the number of submodules which exist for the specified module |
|
995 @param aName module to count submodules for |
|
996 @param aNumSubs number of submodules for module |
|
997 @return An error code if module not found |
|
998 */ |
|
999 { |
|
1000 CModule* module = NULL; |
|
1001 // check module/submodule exists |
|
1002 TRAPD(ret, module = GetModulePtrL(aName);) |
|
1003 if (KErrNone != ret) |
|
1004 { |
|
1005 return ret; |
|
1006 } |
|
1007 aNumSubs = module->NumSubModules(); |
|
1008 return KErrNone; |
|
1009 } |
|
1010 |
|
1011 |
|
1012 CBindManager::CBindManager() : |
|
1013 iModuleList(_FOFF(CModule, iLink)), |
|
1014 iJobList(_FOFF(CJob, iLink)), |
|
1015 iBindList(_FOFF(CBindInfo, iLink)), |
|
1016 iEnumBindingsIdx(0) |
|
1017 /** CBindManager constructor |
|
1018 */ |
|
1019 { |
|
1020 } |
|
1021 |
|
1022 CModule* CBindManager::GetModulePtrL(const TCFModuleNameF& aModule) |
|
1023 /** Search method to find a cmodule ptr from a module name |
|
1024 @param aModule name of module to find |
|
1025 @return a pointer to the cmodule |
|
1026 @leave ERSModuleUnknown |
|
1027 */ |
|
1028 { |
|
1029 TDblQueIter<CModule> moduleIter(iModuleList); |
|
1030 CModule *pModule; |
|
1031 while((pModule = moduleIter++) != NULL) |
|
1032 { |
|
1033 if (pModule->Name() == aModule) |
|
1034 { |
|
1035 break; |
|
1036 } |
|
1037 } |
|
1038 if (!pModule) |
|
1039 { |
|
1040 User::Leave(KErrRSModuleUnknown); |
|
1041 } |
|
1042 return pModule; |
|
1043 } |
|
1044 |
|
1045 |
|
1046 CModule* CBindManager::GetModulePtrL(const TCFSubModuleAddress& aSubModuleAddr) |
|
1047 /** Search method to find a cmodule ptr from a submodule address |
|
1048 @param aSubModuleAddr full name of sub module to find |
|
1049 @return a pointer to the cmodule |
|
1050 @leave ERSModuleUnknown |
|
1051 @leave ERSSubModuleUnknown |
|
1052 */ |
|
1053 { |
|
1054 CModule *pModule = GetModulePtrL(aSubModuleAddr.Module()); |
|
1055 if (!pModule->HasSubModule(aSubModuleAddr.SubModule())) |
|
1056 { |
|
1057 User::Leave(KErrRSSubModuleUnknown); |
|
1058 } |
|
1059 return pModule; |
|
1060 } |
|
1061 |
|
1062 |
|
1063 void CBindManager::TaskCompleted(CModule &aModule, const CTask &aTask, |
|
1064 TInt aStatus) |
|
1065 /** Called by a cmodule when a task is completed. Bindmanager passes the |
|
1066 information to all jobs and bindinfos |
|
1067 @param aModule the cmodule which owns the completed task |
|
1068 @param aTask the task which has finished |
|
1069 @param aStatus the status returned by the completed task |
|
1070 */ |
|
1071 { |
|
1072 __CFLOG_VAR((KLogSubSysRS, KLogCode, _L8("CBindManager::TaskCompleted(%X = %S, %d, %d)"), &aModule, &aModule.Name(), aTask.TaskId(), aStatus)); |
|
1073 |
|
1074 // inform all jobs |
|
1075 TDblQueIter<CJob> jobIter(iJobList); |
|
1076 CJob *pJob; |
|
1077 while((pJob = jobIter++) != NULL) |
|
1078 { |
|
1079 pJob->TaskCompleted(aModule.Name(), aTask.TaskId(), aStatus); |
|
1080 } |
|
1081 |
|
1082 // update any bindinfos |
|
1083 TDblQueIter<CBindInfo> bindIter(iBindList); |
|
1084 CBindInfo *pBind; |
|
1085 while((pBind = bindIter++) != NULL) |
|
1086 { |
|
1087 pBind->TaskCompleted(aTask, aStatus); |
|
1088 } |
|
1089 |
|
1090 // if a discoveryresp completed without error then update module state |
|
1091 if (aTask.Message().Code() == TCFCommsMessage::ECodeDiscover && |
|
1092 aStatus == KErrNone) |
|
1093 { |
|
1094 __ASSERT_DEBUG(aModule.Initialising(), User::Panic(KBindMgrPanic, EDiscoveryRespOutOfSequence)); |
|
1095 aModule.SetInitialising(EFalse); |
|
1096 } |
|
1097 else if (aTask.Message().Code() == TCFCommsMessage::ECodeBind) // remove refs to moduleAddr. message now becomes unusable. |
|
1098 { |
|
1099 const TCFBindMsg& bmsg = reinterpret_cast<const TCFBindMsg&>(aTask.Message()); |
|
1100 iModuleNameStor->Remove(*bmsg.SubModule1()); |
|
1101 iModuleNameStor->Remove(*bmsg.SubModule2()); |
|
1102 } |
|
1103 else if (aTask.Message().Code() == TCFCommsMessage::ECodeUnbind) |
|
1104 { |
|
1105 const TCFUnbindMsg& ubmsg = reinterpret_cast<const TCFUnbindMsg&>(aTask.Message()); |
|
1106 iModuleNameStor->Remove(*ubmsg.SubModule1()); |
|
1107 iModuleNameStor->Remove(*ubmsg.SubModule2()); |
|
1108 } |
|
1109 } |
|
1110 |
|
1111 |
|
1112 void CBindManager::ReceivedMessage(const TCFModuleNameF& aModule, |
|
1113 const TCFMessage& aNewMsg) |
|
1114 /** Called by a cmodule when a message with no associated task is received. The |
|
1115 bindmanager passes the message to the rootserver. |
|
1116 @param aModule the name of the module which received the message |
|
1117 @param aNewMsg the received message |
|
1118 */ |
|
1119 { |
|
1120 __CFLOG(KLogSubSysRS, KLogCode, _L8("CBindManager::ReceivedMessage")); |
|
1121 iNotify->ReceivedMessage(aModule, aNewMsg); |
|
1122 } |
|
1123 |
|
1124 |
|
1125 void CBindManager::JobTimedOut(const TCFModuleNameF &aModuleName, const TUint aTaskId) |
|
1126 /** Called by a cjob for each taskid when it times out. It informs the associated |
|
1127 module. |
|
1128 @param aModuleName the name of the module associated with the task |
|
1129 @param aTaskId the id of the task |
|
1130 */ |
|
1131 { |
|
1132 __CFLOG_2(KLogSubSysRS, KLogCode, _L8("CBindManager::JobTimedOut(%S, %d)"), &aModuleName, aTaskId); |
|
1133 |
|
1134 CModule* pModule = 0; |
|
1135 TRAPD(ret, pModule = GetModulePtrL(aModuleName)); |
|
1136 ret = ret; // suppress "unused var" warning from release builds |
|
1137 __ASSERT_DEBUG(KErrNone==ret, User::Panic(KBindMgrPanic, EModuleRefMissing)); |
|
1138 if (pModule) |
|
1139 { |
|
1140 pModule->EndTask(aTaskId, KErrRSRequestTimedOut); |
|
1141 } |
|
1142 } |
|
1143 |
|
1144 |