37 using namespace CommsFW; |
37 using namespace CommsFW; |
38 |
38 |
39 // |
39 // |
40 // CSockSessionProxy |
40 // CSockSessionProxy |
41 // |
41 // |
42 |
|
43 EXPORT_C CCommonSessionProxy::CCommonSessionProxy(CWorkerSession* aSession, CCommonPlayer& aPlayer) |
42 EXPORT_C CCommonSessionProxy::CCommonSessionProxy(CWorkerSession* aSession, CCommonPlayer& aPlayer) |
44 : iSession(aSession), |
43 : iSession(aSession), |
45 iPlayer(aPlayer), |
44 iPlayer(aPlayer), |
46 iNumSubSessClosing(ELivingSession), |
45 iNumSubSessClosing(ELivingSession) |
47 iSubSessionCloseThrottle(*this) |
|
48 { |
46 { |
49 //COMMONLOG((WorkerId(),KECommonBootingTag, _L8("CSockSessionProxy %08x:\tCSockSessionProxy(), iSockSession %08x"), this, iSession) ); |
47 //COMMONLOG((WorkerId(),KECommonBootingTag, _L8("CSockSessionProxy %08x:\tCSockSessionProxy(), iSockSession %08x"), this, iSession) ); |
50 } |
48 } |
51 |
49 |
52 EXPORT_C CCommonSessionProxy::~CCommonSessionProxy() |
50 EXPORT_C CCommonSessionProxy::~CCommonSessionProxy() |
66 CCommonWorkerThread& worker = iPlayer.WorkerThread(); |
64 CCommonWorkerThread& worker = iPlayer.WorkerThread(); |
67 worker.IncProlongBindingLife(); |
65 worker.IncProlongBindingLife(); |
68 __ASSERT_DEBUG(!IsClosing(), User::Panic(KSpecAssert_ElemSvrDenPlayrC, 1)); |
66 __ASSERT_DEBUG(!IsClosing(), User::Panic(KSpecAssert_ElemSvrDenPlayrC, 1)); |
69 iNumSubSessClosing = 1; // dummy subsession to prevent premature suicide during this close loop |
67 iNumSubSessClosing = 1; // dummy subsession to prevent premature suicide during this close loop |
70 |
68 |
71 |
69 // The object container is stored as a packed array, so working backwards through it avoids invalidating |
72 DeleteSubSessionsWithThrottling(); |
70 // the iterator when removing entries (and as a bonus is more efficient) |
73 } |
71 CCommonPlayer::TSubSessionContainer& subSessions(iPlayer.SubSessions()); |
74 |
72 for(TInt i = subSessions.Count() - 1; i >= 0; --i) |
75 void CCommonSessionProxy::DeleteSubSessionsWithThrottling() |
73 { |
76 { |
74 CWorkerSubSession* subSession = subSessions[i]; |
77 // Why Throttle? The original scenario is a process which opens a large number of sockets (100 in the |
75 if(subSession->Session() == iSession) |
78 // original case) and terminates without closing them, leaving BeginSessionClose() to clean them up. |
76 { |
79 // In addition, the worker in question (pdummy1) synchronously deletes subsessions (1) and uses a shared |
77 ++iNumSubSessClosing; |
80 // shared heap configuration (i.e. limited memory). As each deletion results in a message being sent |
78 if(!subSession->IsClosing()) |
81 // (to an SCPR), and there is no opportunity to drain these due to the synchronous deletion, the transport |
79 { |
82 // queue overflows and cannot be grown resulting in a panic. So use a (*low* priority) active object to |
80 subSession->DeleteMe(); |
83 // delete a limited number of subsessions per RunL(). |
81 } |
84 // |
82 } |
85 // (1) a call to DeleteMe() results in an immediate upcall to NotifySubSessionDestroyed(). |
83 } |
86 |
84 |
87 TInt count = KSubSessionThrottleSize; |
85 NotifySubSessionDestroyed(); // remove the dummy subsession |
88 |
86 } |
89 // The object container is stored as a packed array, so working backwards through it avoids invalidating |
|
90 // the iterator when removing entries (and as a bonus is more efficient) |
|
91 |
|
92 CCommonPlayer::TSubSessionContainer& subSessions(iPlayer.SubSessions()); |
|
93 for(TInt i = subSessions.Count() - 1; i >= 0; --i) |
|
94 { |
|
95 CWorkerSubSession* subSession = subSessions[i]; |
|
96 if(subSession->Session() == iSession) |
|
97 { |
|
98 ++iNumSubSessClosing; |
|
99 if(!subSession->IsClosing()) |
|
100 { |
|
101 subSession->DeleteMe(); |
|
102 // Throttle the deletions as appropriate |
|
103 if (--count <= 0) |
|
104 { |
|
105 COMMONLOG((Player().WorkerId(),KECommonBootingTag, _L8("CCommonSessionProxy %08x:\tDeleteSubSessionBunch(): throttled subsession deletion"), this) ); |
|
106 // Re-prime the one shot |
|
107 iSubSessionCloseThrottle.Call(); |
|
108 return; |
|
109 } |
|
110 } |
|
111 } |
|
112 } |
|
113 NotifySubSessionDestroyed(); // all, done, remove the dummy subsession |
|
114 } |
|
115 |
87 |
116 EXPORT_C void CCommonSessionProxy::NotifySubSessionDestroyed() |
88 EXPORT_C void CCommonSessionProxy::NotifySubSessionDestroyed() |
117 { |
89 { |
118 //COMMONLOG((Player().WorkerId(),KECommonBootintgTag, _L8("CCommonSessionProxy %08x:\tNotifySubSessionDestroyed(), iSockSession %08x"), this, iSession) ); |
90 //COMMONLOG((Player().WorkerId(),KECommonBootingTag, _L8("CCommonSessionProxy %08x:\tNotifySubSessionDestroyed(), iSockSession %08x"), this, iSession) ); |
119 if(IsClosing() &&--iNumSubSessClosing <= 0) |
91 if(IsClosing() && --iNumSubSessClosing <= 0) |
120 { |
92 { |
121 __ASSERT_DEBUG(iNumSubSessClosing == 0, User::Panic(KSpecAssert_ElemSvrDenPlayrC, 2)); |
93 __ASSERT_DEBUG(iNumSubSessClosing == 0, User::Panic(KSpecAssert_ElemSvrDenPlayrC, 2)); |
122 CCommonWorkerThread& worker = iPlayer.WorkerThread(); |
94 CCommonWorkerThread& worker = iPlayer.WorkerThread(); |
123 worker.CompleteSessionClose(iSession); |
95 worker.CompleteSessionClose(iSession); |
124 delete this; |
96 delete this; |
125 } |
97 } |
126 } |
98 } |
127 |
99 |
128 // |
|
129 // CCommonSessionProxy::CSubSessionCloseThrottle |
|
130 // |
|
131 |
|
132 CCommonSessionProxy::CSubSessionCloseThrottle::CSubSessionCloseThrottle(CCommonSessionProxy& aProxy) |
|
133 : CAsyncOneShot(EPriorityLow), iProxy(aProxy) // This must be low priority! |
|
134 { |
|
135 } |
|
136 |
|
137 void CCommonSessionProxy::CSubSessionCloseThrottle::RunL() |
|
138 { |
|
139 // Delete some more subsessions |
|
140 iProxy.DeleteSubSessionsWithThrottling(); |
|
141 } |
|
142 |
100 |
143 // |
101 // |
144 // CCommonPlayer |
102 // CCommonPlayer |
145 // |
103 // |
146 |
104 |