|
1 // Copyright (c) 2010 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 // Flow / Binder |
|
15 // (data plane) |
|
16 // |
|
17 // |
|
18 // This is a 3-plane comms layer implementation example, which has been customised to be a test layer which gobbles and releases ESOCK MBUFs. |
|
19 // The MBuf gobbling functionality can be disabled by undefining the macro SYMBIAN_COMMSFW_MBUF_GOBBLER which is specified in mbufgobblerproviders.mmp. |
|
20 // When SYMBIAN_COMMSFW_MBUF_GOBBLER is undefined, the source code specified by mbufgobblerproviders.mmp becomes a pass through layer i.e. it passes the data |
|
21 // through to the layer above or below without altering it. This makes it useful as a starting point for implementing your own layers / providers; |
|
22 // useful documentation on how to customise your own passthrough layer can be found in ..\docs\MbufGobblerLayer.doc |
|
23 // |
|
24 /** |
|
25 @file |
|
26 @internalComponent |
|
27 */ |
|
28 |
|
29 #include <comms-infras/ss_activities.h> |
|
30 #include <comms-infras/ss_logext.h> |
|
31 #include <es_mbman.h> |
|
32 #include <mbufgobblerpubsub.h> |
|
33 #include "mbufgobblerflow.h" |
|
34 #include "mbufgobblerlog.h" |
|
35 |
|
36 // for panics |
|
37 _LIT(KPanicCategory, "MbufGobblerLayer"); |
|
38 enum |
|
39 { |
|
40 KPanic_DestroyReceivedBeforeUnbind = 2001 |
|
41 }; |
|
42 |
|
43 _LIT8(KNodeName, "CMbufGobblerFlow"); |
|
44 |
|
45 |
|
46 /////////////////////////// |
|
47 // class CMbufGobblerFlow // |
|
48 /////////////////////////// |
|
49 |
|
50 CMbufGobblerFlow* CMbufGobblerFlow::NewL(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf) |
|
51 { |
|
52 CMbufGobblerFlow* inst = new(ELeave) CMbufGobblerFlow(aFactory, aSubConnId, aProtocolIntf); |
|
53 CleanupStack::PushL(inst); |
|
54 inst->ConstructL(); |
|
55 CleanupStack::Pop(inst); |
|
56 return inst; |
|
57 } |
|
58 |
|
59 CMbufGobblerFlow::CMbufGobblerFlow(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf) |
|
60 /** |
|
61 * Constructor. |
|
62 * |
|
63 * @param aFactory Reference to the factory which created this object. |
|
64 * @param aTheLogger The logging object, ownership is passed to this object |
|
65 */ |
|
66 :ESock::CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf) |
|
67 { |
|
68 MBUFGOBBLER_LOG_NODE_CREATE(KMbufGobblerFlowSubTag, CMbufGobblerFlow, KNodeName, this->NodeId().Ptr()); |
|
69 } |
|
70 |
|
71 void CMbufGobblerFlow::ConstructL() |
|
72 { |
|
73 #ifdef SYMBIAN_COMMSFW_MBUF_GOBBLER |
|
74 iMBufGobbler = CMBufGobbler::NewL(); |
|
75 #endif |
|
76 } |
|
77 |
|
78 CMbufGobblerFlow::~CMbufGobblerFlow() |
|
79 { |
|
80 MBUFGOBBLER_LOG_NODE_DESTROY(KMbufGobblerFlowSubTag, CMbufGobblerFlow, KNodeName, this->NodeId().Ptr()); |
|
81 iBinders.ResetAndDestroy(); |
|
82 #ifdef SYMBIAN_COMMSFW_MBUF_GOBBLER |
|
83 delete iMBufGobbler; |
|
84 #endif |
|
85 } |
|
86 |
|
87 |
|
88 |
|
89 /////////////////////////////////////////// |
|
90 // Methods from CSubConnectionFlowBase: // |
|
91 /////////////////////////////////////////// |
|
92 |
|
93 ESock::MFlowBinderControl* CMbufGobblerFlow::DoGetBinderControlL() |
|
94 { |
|
95 return this; |
|
96 } |
|
97 |
|
98 |
|
99 // Messages::ANode |
|
100 void CMbufGobblerFlow::ReceivedL( |
|
101 const Messages::TRuntimeCtxId& aSender, |
|
102 const Messages::TNodeId& aRecipient, |
|
103 Messages::TSignatureBase& aMessage |
|
104 ) |
|
105 /** |
|
106 Method called on incoming SCPR messages |
|
107 |
|
108 @param aCFMessage message base |
|
109 */ |
|
110 { |
|
111 |
|
112 LOGMESSAGE(KMbufGobblerFlowSubTag, KNodeName, this, aSender, aRecipient, aMessage); |
|
113 //LOG_NODE_INFO(KMbufGobblerFlowSubTag, KNodeName, *this); does not compile as flow inheritance is different to other nodes |
|
114 CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage); |
|
115 |
|
116 // Dispatch the message locally |
|
117 if (ESock::TCFDataClient::ERealmId == aMessage.MessageId().Realm()) |
|
118 { |
|
119 switch (aMessage.MessageId().MessageId()) |
|
120 { |
|
121 |
|
122 case ESock::TCFDataClient::TStart::EId : |
|
123 { |
|
124 iSubConnectionProvider.RNodeInterface::PostMessage( |
|
125 Id(), |
|
126 ESock::TCFDataClient::TStarted().CRef() |
|
127 ); |
|
128 } |
|
129 break; |
|
130 |
|
131 case ESock::TCFDataClient::TStop::EId : |
|
132 { |
|
133 TInt i; |
|
134 for (i=iBinders.Count()-1;i>=0;--i) |
|
135 { |
|
136 CMbufGobblerBinder* binder = iBinders[i]; |
|
137 binder->UnbindFromLowerFlow(); |
|
138 delete binder; |
|
139 iBinders.Remove(i); |
|
140 } |
|
141 iSubConnectionProvider.PostMessage(Id(), ESock::TCFDataClient::TStopped(KErrNone).CRef()); |
|
142 } |
|
143 break; |
|
144 |
|
145 case ESock::TCFDataClient::TProvisionConfig::EId : |
|
146 { |
|
147 ESock::TCFDataClient::TProvisionConfig& aMess = Messages::message_cast<ESock::TCFDataClient::TProvisionConfig>(aMessage); |
|
148 iAccessPointConfig.Close(); |
|
149 iAccessPointConfig.Open(aMess.iConfig); |
|
150 } |
|
151 break; |
|
152 |
|
153 case ESock::TCFDataClient::TBindTo::EId : |
|
154 { |
|
155 ESock::TCFDataClient::TBindTo& bindToReq = Messages::message_cast<ESock::TCFDataClient::TBindTo>(aMessage); |
|
156 if (bindToReq.iNodeId == Messages::TNodeId::NullId()) |
|
157 { |
|
158 User::Leave(KErrNotSupported); |
|
159 } |
|
160 |
|
161 const Messages::TNodeId& commsId = bindToReq.iNodeId; |
|
162 CSubConnectionFlowBase* lowerFlow = Messages::mnode_cast<CSubConnectionFlowBase>(&commsId.Node()); |
|
163 |
|
164 MFlowBinderControl* lowerBinderControl = lowerFlow->GetBinderControlL(); |
|
165 ASSERT(lowerBinderControl); |
|
166 |
|
167 TInt i; |
|
168 for (i=0;i<iBinders.Count();++i) |
|
169 { |
|
170 // binder for each protocol will request binder for same protocol from lower binder controller using this fn. |
|
171 iBinders[i]->BindToLowerFlowL(*lowerBinderControl); |
|
172 } |
|
173 ASSERT(i); // there should be some binders! |
|
174 |
|
175 Messages::RClientInterface::OpenPostMessageClose( |
|
176 Id(), |
|
177 aSender, |
|
178 ESock::TCFDataClient::TBindToComplete().CRef() |
|
179 ); |
|
180 } |
|
181 break; |
|
182 |
|
183 default: |
|
184 ASSERT(EFalse); |
|
185 } |
|
186 } |
|
187 else if (Messages::TEChild::ERealmId == aMessage.MessageId().Realm()) |
|
188 { |
|
189 switch (aMessage.MessageId().MessageId()) |
|
190 { |
|
191 case Messages::TEChild::TDestroy::EId : |
|
192 { |
|
193 TInt i; |
|
194 for (i=0;i<iBinders.Count();++i) |
|
195 { |
|
196 // ensure all binders unbound |
|
197 if (iBinders[i]->InUse()) |
|
198 { |
|
199 //__CFLOG_0(KLogTag1, KLogTag2,_L("something is sending TDestroy to CMbufGobblerFlow before unbinding.")); |
|
200 User::Panic(KPanicCategory,KPanic_DestroyReceivedBeforeUnbind); |
|
201 } |
|
202 |
|
203 // EXAMPLE CODE: cancel requests here if necessary... |
|
204 //iBinders[i]->Cancel(); |
|
205 |
|
206 } |
|
207 if (i==iBinders.Count()) // all unbound |
|
208 { |
|
209 DeleteThisFlow(); |
|
210 } |
|
211 } |
|
212 break; |
|
213 |
|
214 default: |
|
215 ASSERT(EFalse); |
|
216 } |
|
217 } |
|
218 // realm != TCFMessage::ERealmId |
|
219 else |
|
220 { |
|
221 ASSERT(EFalse); |
|
222 } |
|
223 } |
|
224 |
|
225 |
|
226 /////////////////////////////////////// |
|
227 // Methods from MFlowBinderControl: // |
|
228 /////////////////////////////////////// |
|
229 |
|
230 ESock::MLowerControl* CMbufGobblerFlow::GetControlL(const TDesC8& aProtocol) |
|
231 /** |
|
232 Create and return an MLowerControl instance of the specified binder type. |
|
233 |
|
234 Called from upper layer during binding procedure. |
|
235 |
|
236 @param aProtocol Protocol type of the binder |
|
237 @return MLowerControl instance of the protocol type |
|
238 */ |
|
239 { |
|
240 ESock::MLowerControl* lowerControl = FindOrCreateBinderL(aProtocol); |
|
241 ASSERT(lowerControl); |
|
242 return lowerControl; |
|
243 } |
|
244 |
|
245 |
|
246 ESock::MLowerDataSender* CMbufGobblerFlow::BindL(const TDesC8& aProtocol, ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl) |
|
247 { |
|
248 CMbufGobblerBinder* binder = FindOrCreateBinderL(aProtocol); |
|
249 ASSERT(binder); |
|
250 binder->BindToUpperL( *aReceiver, *aControl ); |
|
251 |
|
252 iSubConnectionProvider.RNodeInterface::PostMessage( |
|
253 Id(), |
|
254 ESock::TCFControlProvider::TActive().CRef() |
|
255 ); |
|
256 |
|
257 return binder; |
|
258 } |
|
259 |
|
260 void CMbufGobblerFlow::Unbind( ESock::MUpperDataReceiver* aReceiver, ESock::MUpperControl* aControl) |
|
261 { |
|
262 ASSERT(aReceiver); |
|
263 ASSERT(aControl); |
|
264 TInt i; |
|
265 TInt numberUnbound=0; |
|
266 for (i=0;i<iBinders.Count();++i) |
|
267 { |
|
268 numberUnbound += (iBinders[i]->UnbindFromUpper(*aReceiver,*aControl) ? 1 : 0); |
|
269 } |
|
270 ASSERT(i); // there should be some binders! |
|
271 ASSERT(numberUnbound<=1); // only 1 unbind should have happened |
|
272 |
|
273 iSubConnectionProvider.RNodeInterface::PostMessage( |
|
274 Id(), |
|
275 ESock::TCFControlProvider::TIdle().CRef() |
|
276 ); |
|
277 } |
|
278 |
|
279 ESock::CSubConnectionFlowBase* CMbufGobblerFlow::Flow() |
|
280 { |
|
281 return this; |
|
282 } |
|
283 |
|
284 |
|
285 ///////////////// |
|
286 // Own methods // |
|
287 ///////////////// |
|
288 |
|
289 CMbufGobblerBinder* CMbufGobblerFlow::FindOrCreateBinderL(const TDesC8& aProtocol) |
|
290 { |
|
291 |
|
292 // EXAMPLE CODE, should you want your: perhaps your protocol to work with IPv4 |
|
293 //if (aProtocol.Compare(KIp4ProtocolName)) |
|
294 // { // only work with IPv4 |
|
295 // User::Leave(KErrNotSupported); |
|
296 // } |
|
297 |
|
298 for (TInt i=0;i<iBinders.Count();++i) |
|
299 { |
|
300 if(iBinders[i]->ProtocolName() == aProtocol) |
|
301 { |
|
302 return iBinders[i]; |
|
303 } |
|
304 } |
|
305 // not found.. create it. |
|
306 CMbufGobblerBinder* newBinder = CMbufGobblerBinder::NewL(aProtocol); |
|
307 CleanupStack::PushL(newBinder); |
|
308 iBinders.AppendL(newBinder); |
|
309 CleanupStack::Pop(newBinder); |
|
310 return newBinder; |
|
311 } |
|
312 |
|
313 |
|
314 |
|
315 |
|
316 |
|
317 //################################################################################################## |
|
318 |
|
319 ///////////////////////////// |
|
320 // class CMbufGobblerBinder // |
|
321 ///////////////////////////// |
|
322 |
|
323 |
|
324 //////////////////// |
|
325 // My constructor // |
|
326 //////////////////// |
|
327 |
|
328 CMbufGobblerBinder::CMbufGobblerBinder(const TDesC8& aProtocolName): |
|
329 iLowerControl(NULL), |
|
330 iLowerDataSender(NULL), |
|
331 iUpperControl(NULL), |
|
332 iUpperDataReceiver(NULL), |
|
333 iProtocolName(aProtocolName) |
|
334 {} |
|
335 |
|
336 CMbufGobblerBinder* CMbufGobblerBinder::NewL(const TDesC8& aProtocolName) |
|
337 { |
|
338 CMbufGobblerBinder* inst = new(ELeave) CMbufGobblerBinder(aProtocolName); |
|
339 CleanupStack::PushL(inst); |
|
340 inst->ConstructL(); |
|
341 CleanupStack::Pop(inst); |
|
342 return inst; |
|
343 } |
|
344 |
|
345 void CMbufGobblerBinder::ConstructL() |
|
346 { |
|
347 MBUFGOBBLER_TEST_DATA_INIT |
|
348 #if 0 |
|
349 // EXAMPLE CODE - set up everything you need to in this method. |
|
350 // Perhaps you have some kind of test control interface using pub/sub.. if so you'd do something like below.. |
|
351 // Diff this file with networking/netperf/delaymeterproto/src/delaymeterflow.cpp for a full working implementation of such a control interface... |
|
352 CActiveScheduler::Add(this); |
|
353 DefinePubSubKeysL(); |
|
354 // watch for incoming commands |
|
355 User::LeaveIfError(iProperty.Attach(TUid::Uid(KDelayMeterControlLevel), KCommandToDelayMeter)); |
|
356 iProperty.Subscribe(iStatus); |
|
357 SetActive(); |
|
358 #endif |
|
359 } |
|
360 |
|
361 /*virtual*/ |
|
362 CMbufGobblerBinder::~CMbufGobblerBinder() |
|
363 { |
|
364 } |
|
365 |
|
366 |
|
367 |
|
368 //////////////////////////////////////// |
|
369 // Methods from ESock::MLowerControl: // |
|
370 //////////////////////////////////////// |
|
371 |
|
372 TInt CMbufGobblerBinder::GetName(TDes& aName) |
|
373 { |
|
374 TBuf16<10> tmp; |
|
375 tmp.Copy(ProtocolName()); |
|
376 aName.Format(_L("mbufgobbler[%S][0x%08x]"), &tmp, this); |
|
377 |
|
378 return KErrNone; |
|
379 } |
|
380 |
|
381 TInt CMbufGobblerBinder::BlockFlow(TBlockOption aOption) |
|
382 { |
|
383 if (iLowerControl==NULL) |
|
384 { |
|
385 return KErrNotReady; |
|
386 } |
|
387 return iLowerControl->BlockFlow(aOption) ; |
|
388 } |
|
389 |
|
390 TInt CMbufGobblerBinder::GetConfig(TBinderConfig& aConfig) |
|
391 { |
|
392 if (iLowerControl==NULL) |
|
393 { |
|
394 return KErrNotReady; |
|
395 } |
|
396 return iLowerControl->GetConfig(aConfig) ; |
|
397 } |
|
398 |
|
399 TInt CMbufGobblerBinder::Control(TUint aLevel, TUint aName, TDes8& aOption) |
|
400 { |
|
401 // Pass it on.. |
|
402 if (iLowerControl==NULL) |
|
403 { |
|
404 return KErrNotReady; |
|
405 } |
|
406 return iLowerControl->Control(aLevel,aName,aOption); |
|
407 } |
|
408 |
|
409 |
|
410 /////////////////////////////////////////// |
|
411 // Methods from ESock::MLowerDataSender: // |
|
412 /////////////////////////////////////////// |
|
413 |
|
414 ESock::MLowerDataSender::TSendResult CMbufGobblerBinder::Send(RMBufChain& aData) |
|
415 { |
|
416 // EXAMPLE NOTE: |
|
417 // This is where a protocol implementation will do its work on outgoing data. |
|
418 |
|
419 MBUFGOBBLER_TEST_POINT(KBinderSend,KErrNone) |
|
420 |
|
421 if (iLowerControl==NULL) |
|
422 { |
|
423 return ESendBlocked; // returning this obliges us to send an unblock later.. |
|
424 // so perhaps it'd be better to just swallow the packet? |
|
425 } |
|
426 return iLowerDataSender->Send(aData); |
|
427 } |
|
428 |
|
429 //////////////////////////////////////// |
|
430 // Methods from ESock::MUpperControl: // |
|
431 //////////////////////////////////////// |
|
432 |
|
433 /*virtual*/ |
|
434 void CMbufGobblerBinder::StartSending() |
|
435 { |
|
436 if (iUpperControl) |
|
437 { |
|
438 iUpperControl->StartSending(); |
|
439 } |
|
440 else |
|
441 { |
|
442 ASSERT(1); // to allow setting a breakpoint |
|
443 //__CFLOG_0(KLogTag1, KLogTag2,_L("CMbufGobblerBinder::StartSending: upper control not yet known!")); |
|
444 } |
|
445 } |
|
446 |
|
447 /*virtual*/ |
|
448 void CMbufGobblerBinder::Error(TInt anError) |
|
449 { |
|
450 if (iUpperControl) |
|
451 { |
|
452 iUpperControl->Error(anError); |
|
453 } |
|
454 else |
|
455 { |
|
456 ASSERT(1); // to set a breakpoint |
|
457 //__CFLOG_0(KLogTag1, KLogTag2,_L("CMbufGobblerBinder::Error: upper control not yet known!")); |
|
458 } |
|
459 } |
|
460 |
|
461 |
|
462 ///////////////////////////////////////////// |
|
463 // Methods from ESock::MUpperDataReceiver: // |
|
464 ///////////////////////////////////////////// |
|
465 |
|
466 /*virtual*/ |
|
467 void CMbufGobblerBinder::Process(RMBufChain& aData) |
|
468 { |
|
469 // EXAMPLE NOTE: |
|
470 // This is where a protocol implementation will do its work on incoming data. |
|
471 |
|
472 MBUFGOBBLER_TEST_POINT(KBinderReceive,KErrNone) |
|
473 |
|
474 if (iUpperDataReceiver == NULL) |
|
475 { |
|
476 // Why is the guy below still sending data to me when I'm not bound above? |
|
477 // Try to ignore it |
|
478 ASSERT(1); // so a breakpoint can be set if necessary |
|
479 //__CFLOG_0(KLogTag1, KLogTag2,_L("CMbufGobblerBinder::Process: incoming traffic discarded as upper data receiver not (or no longer) set")); |
|
480 return; |
|
481 } |
|
482 iUpperDataReceiver->Process(aData); |
|
483 } |
|
484 |
|
485 |
|
486 ////////////////////////// |
|
487 // and my own methods.. // |
|
488 ////////////////////////// |
|
489 |
|
490 // called by layer above calling my flow's BindL |
|
491 void CMbufGobblerBinder::BindToUpperL(MUpperDataReceiver& aUpperDataReceiver, MUpperControl& aUpperControl) |
|
492 { |
|
493 if(iUpperDataReceiver || iUpperControl) {User::Leave(KErrInUse);} |
|
494 iUpperDataReceiver=&aUpperDataReceiver; |
|
495 iUpperControl=&aUpperControl; |
|
496 MBUFGOBBLER_TEST_POINT(KBind,KErrNone) |
|
497 } |
|
498 |
|
499 // called by layer above calling my flow's Unbind. Returns ETrue if unbind happened here, EFalse otherwise |
|
500 TBool CMbufGobblerBinder::UnbindFromUpper(MUpperDataReceiver& aUpperDataReceiver, MUpperControl& aUpperControl) |
|
501 { |
|
502 if(&aUpperDataReceiver == iUpperDataReceiver && &aUpperControl == iUpperControl) |
|
503 { |
|
504 iUpperDataReceiver=0; |
|
505 iUpperControl=0; |
|
506 return ETrue; |
|
507 } |
|
508 return EFalse; |
|
509 } |
|
510 |
|
511 // called by my flow receiving a BinderRequest |
|
512 void CMbufGobblerBinder::BindToLowerFlowL(ESock::MFlowBinderControl& aLowerBinderControl) |
|
513 { |
|
514 // __CFLOG_0(KLogTag1, KLogTag2, _L("CMbufGobblerBinder::BindToLowerFlowL")); |
|
515 if(iLowerControl || iLowerDataSender) |
|
516 { |
|
517 User::Leave(KErrInUse); |
|
518 } |
|
519 |
|
520 iBinderControl = &aLowerBinderControl; |
|
521 iLowerControl = aLowerBinderControl.GetControlL(ProtocolName()); |
|
522 iLowerDataSender = aLowerBinderControl.BindL(ProtocolName(), this, this); |
|
523 } |
|
524 |
|
525 void CMbufGobblerBinder::UnbindFromLowerFlow() |
|
526 { |
|
527 if (!iBinderControl) |
|
528 return; |
|
529 |
|
530 iBinderControl->Unbind(this, this); |
|
531 iBinderControl = NULL; |
|
532 |
|
533 iLowerControl = NULL; |
|
534 iLowerDataSender = NULL; |
|
535 } |
|
536 |
|
537 const TDesC8& CMbufGobblerBinder::ProtocolName() const |
|
538 { |
|
539 return iProtocolName; |
|
540 } |
|
541 |
|
542 #ifdef SYMBIAN_COMMSFW_MBUF_GOBBLER |
|
543 |
|
544 CMBufGobbler::CMBufGobbler(): |
|
545 CActive(CActive::EPriorityStandard) |
|
546 { |
|
547 } |
|
548 |
|
549 CMBufGobbler* CMBufGobbler::NewL() |
|
550 { |
|
551 CMBufGobbler* inst = new(ELeave) CMBufGobbler; |
|
552 CleanupStack::PushL(inst); |
|
553 inst->ConstructL(); |
|
554 CleanupStack::Pop(inst); |
|
555 return inst; |
|
556 } |
|
557 |
|
558 void CMBufGobbler::ConstructL() |
|
559 { |
|
560 iChain.AllocL(128); |
|
561 |
|
562 CActiveScheduler::Add(this); |
|
563 |
|
564 TInt result = RProperty::Define(TUid::Uid(EMBufGobbler), EAdjustNumberOfMBufsRemainingInPool, RProperty::EInt); |
|
565 // Only want 1 instance of a MBufGobbler Layer, so just leave if KErrAlreadyExists returned |
|
566 User::LeaveIfError(result); |
|
567 |
|
568 // watch for incoming commands |
|
569 User::LeaveIfError(iProperty.Attach(TUid::Uid(EMBufGobbler), EAdjustNumberOfMBufsRemainingInPool)); |
|
570 |
|
571 iProperty.Subscribe(iStatus); |
|
572 SetActive(); |
|
573 } |
|
574 |
|
575 /*virtual*/ CMBufGobbler::~CMBufGobbler() |
|
576 { |
|
577 if (IsActive()) |
|
578 { |
|
579 Cancel(); |
|
580 } |
|
581 |
|
582 iChain.Free(); |
|
583 |
|
584 TInt result = RProperty::Delete(TUid::Uid(EMBufGobbler), EAdjustNumberOfMBufsRemainingInPool); |
|
585 if (result != KErrNone) |
|
586 { |
|
587 RDebug::Print(_L("CMBufGobbler::~CMBufGobbler() %d"), result); |
|
588 } |
|
589 } |
|
590 |
|
591 /*virtual*/ void CMBufGobbler::DoCancel() |
|
592 { |
|
593 iProperty.Cancel(); |
|
594 } |
|
595 |
|
596 /*virtual*/ void CMBufGobbler::RunL() |
|
597 { |
|
598 // Resubscribe to ensure that next pub/sub notification is picked up |
|
599 iProperty.Subscribe(iStatus); |
|
600 SetActive(); |
|
601 |
|
602 TInt request=EGobbleAllMBufs; |
|
603 TInt pubSubRet = iProperty.Get(request); |
|
604 if (pubSubRet == KErrNone) |
|
605 { |
|
606 switch(request) |
|
607 { |
|
608 case EGobbleAllMBufs: |
|
609 { |
|
610 RMBufAllocator allocator; |
|
611 RMBufChain chain; |
|
612 TInt size = allocator.NextMBufSize(0); |
|
613 while (size != KErrNotFound) |
|
614 { |
|
615 TInt ret = KErrNone; |
|
616 while (ret == KErrNone) |
|
617 { |
|
618 ret = chain.Alloc(size); |
|
619 if (ret==KErrNone ) |
|
620 { |
|
621 iChain.Append(chain); |
|
622 } |
|
623 } |
|
624 size = allocator.NextMBufSize(size); |
|
625 } |
|
626 TInt length = iChain.Length(); |
|
627 RDebug::Print(_L("Out of MBuf Memory... Total MBuf memory in use %d"), length); |
|
628 TInt numBufs = iChain.NumBufs(); |
|
629 RDebug::Print(_L("Out of MBuf Memory... Total MBufs in use %d"), numBufs); |
|
630 break; |
|
631 } |
|
632 case EReleaseAllMBufs: |
|
633 { |
|
634 if(!iChain.IsEmpty()) |
|
635 { |
|
636 iChain.Free(); |
|
637 ASSERT(!iChain.Length()); |
|
638 } |
|
639 break; |
|
640 } |
|
641 case EReleaseASingleMBuf: |
|
642 { |
|
643 TInt length = iChain.Length(); |
|
644 if (length != 0) |
|
645 { |
|
646 TInt trimOffset = length - iChain.Last()->Size(); |
|
647 iChain.TrimEnd(trimOffset); |
|
648 } |
|
649 |
|
650 length = iChain.Length(); |
|
651 RDebug::Print(_L("MBufMemory De-Allocated... Total MBuf memory in use %d"), length); |
|
652 break; |
|
653 } |
|
654 default: |
|
655 { |
|
656 RDebug::Print(_L("CMBufGobbler::RunL(), invalid request %d"), request); |
|
657 break; |
|
658 } |
|
659 } |
|
660 } |
|
661 else |
|
662 { |
|
663 RDebug::Print(_L("Attempt to process MBufGobbler publish/subscribe failed with value for %d"), pubSubRet); |
|
664 } |
|
665 } |
|
666 |
|
667 #endif |