sl@0
|
1 |
/*
|
sl@0
|
2 |
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
3 |
* All rights reserved.
|
sl@0
|
4 |
* This component and the accompanying materials are made available
|
sl@0
|
5 |
* under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
6 |
* which accompanies this distribution, and is available
|
sl@0
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
8 |
*
|
sl@0
|
9 |
* Initial Contributors:
|
sl@0
|
10 |
* Nokia Corporation - initial contribution.
|
sl@0
|
11 |
*
|
sl@0
|
12 |
* Contributors:
|
sl@0
|
13 |
*
|
sl@0
|
14 |
* Description:
|
sl@0
|
15 |
* Implements CScsServer functionality. See class and functions definitions
|
sl@0
|
16 |
* for more detail.
|
sl@0
|
17 |
*
|
sl@0
|
18 |
*/
|
sl@0
|
19 |
|
sl@0
|
20 |
|
sl@0
|
21 |
/**
|
sl@0
|
22 |
@file
|
sl@0
|
23 |
*/
|
sl@0
|
24 |
|
sl@0
|
25 |
#include <scs/scsserver.h>
|
sl@0
|
26 |
#include "scsserverconstants.h"
|
sl@0
|
27 |
|
sl@0
|
28 |
static const TInt defaultPolicyRangeCount = 1;
|
sl@0
|
29 |
static const TInt defaultPolicyRanges[defaultPolicyRangeCount] =
|
sl@0
|
30 |
{
|
sl@0
|
31 |
0 // All requests
|
sl@0
|
32 |
};
|
sl@0
|
33 |
|
sl@0
|
34 |
static const TUint8 defaultPolicyElementsIndex[defaultPolicyRangeCount] =
|
sl@0
|
35 |
{
|
sl@0
|
36 |
CPolicyServer::EAlwaysPass
|
sl@0
|
37 |
};
|
sl@0
|
38 |
|
sl@0
|
39 |
static const CPolicyServer::TPolicyElement defaultPolicyPolicyElements[1] = {};
|
sl@0
|
40 |
|
sl@0
|
41 |
|
sl@0
|
42 |
static const CPolicyServer::TPolicy defaultPolicy =
|
sl@0
|
43 |
{
|
sl@0
|
44 |
CPolicyServer::EAlwaysPass, // Allow all connects
|
sl@0
|
45 |
defaultPolicyRangeCount,
|
sl@0
|
46 |
defaultPolicyRanges,
|
sl@0
|
47 |
defaultPolicyElementsIndex,
|
sl@0
|
48 |
defaultPolicyPolicyElements,
|
sl@0
|
49 |
};
|
sl@0
|
50 |
|
sl@0
|
51 |
EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, CActive::TPriority aPriority)
|
sl@0
|
52 |
/**
|
sl@0
|
53 |
Record this server's version so it can be compared against the requested
|
sl@0
|
54 |
version in NewSessionL.
|
sl@0
|
55 |
|
sl@0
|
56 |
@param aVersion This server's version. This is compared against each
|
sl@0
|
57 |
client's requested version when the client tries to connect.
|
sl@0
|
58 |
@param aPriority This server's active object priority.
|
sl@0
|
59 |
*/
|
sl@0
|
60 |
: CPolicyServer(aPriority, defaultPolicy, ESharableSessions)
|
sl@0
|
61 |
,iVersion(aVersion)
|
sl@0
|
62 |
// ,iSessionCount(0)
|
sl@0
|
63 |
{
|
sl@0
|
64 |
// empty.
|
sl@0
|
65 |
}
|
sl@0
|
66 |
|
sl@0
|
67 |
EXPORT_C CScsServer::CScsServer(const TVersion& aVersion, const CPolicyServer::TPolicy& aPolicy, CActive::TPriority aPriority)
|
sl@0
|
68 |
/**
|
sl@0
|
69 |
Record this server's version so it can be compared against the requested
|
sl@0
|
70 |
version in NewSessionL.
|
sl@0
|
71 |
|
sl@0
|
72 |
@param aVersion This server's version. This is compared against each
|
sl@0
|
73 |
client's requested version when the client tries to connect.
|
sl@0
|
74 |
@param aPolicy Can be used to configure security for server connect and session functions
|
sl@0
|
75 |
@param aPriority This server's active object priority.
|
sl@0
|
76 |
|
sl@0
|
77 |
Note that aPolicy must be configured to allow all functions
|
sl@0
|
78 |
covered by the KScsFunctionMask mask.
|
sl@0
|
79 |
*/
|
sl@0
|
80 |
: CPolicyServer(aPriority, aPolicy, ESharableSessions)
|
sl@0
|
81 |
,iVersion(aVersion)
|
sl@0
|
82 |
// ,iSessionCount(0)
|
sl@0
|
83 |
{
|
sl@0
|
84 |
// empty.
|
sl@0
|
85 |
}
|
sl@0
|
86 |
|
sl@0
|
87 |
EXPORT_C void CScsServer::ConstructL(TInt aShutdownPeriodUs)
|
sl@0
|
88 |
/**
|
sl@0
|
89 |
Second-phase constructor allocates the shutdown timer for this server object.
|
sl@0
|
90 |
|
sl@0
|
91 |
If aShutdownPeriodUs is not 0, this function starts the shutdown
|
sl@0
|
92 |
timer because the server starts up with no current sessions.
|
sl@0
|
93 |
|
sl@0
|
94 |
If aShutdownPeriodUs is 0, the timer is not started and the server
|
sl@0
|
95 |
will not auto-exit.
|
sl@0
|
96 |
|
sl@0
|
97 |
nb. It must be called, even if you do not want a shutdown timer.
|
sl@0
|
98 |
|
sl@0
|
99 |
This function does not start the server, i.e. it does not call StartL. The
|
sl@0
|
100 |
calling function must do this after this function returns.
|
sl@0
|
101 |
|
sl@0
|
102 |
@param aShutdownPeriodUs Shutdown period in microseconds.
|
sl@0
|
103 |
*/
|
sl@0
|
104 |
{
|
sl@0
|
105 |
if(aShutdownPeriodUs > 0)
|
sl@0
|
106 |
{
|
sl@0
|
107 |
iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
|
sl@0
|
108 |
iShutdownTimer->Restart();
|
sl@0
|
109 |
}
|
sl@0
|
110 |
|
sl@0
|
111 |
iContainerIndex = CObjectConIx::NewL();
|
sl@0
|
112 |
|
sl@0
|
113 |
TCallBack cb(RemoveCompletedRequests, this);
|
sl@0
|
114 |
// EPriorityHigh to encourage the active scheduler to action the
|
sl@0
|
115 |
// delete ASAP, in particular ahead of pending or new requests.
|
sl@0
|
116 |
iAsyncCleanup = new(ELeave) CAsyncCallBack(cb, CActive::EPriorityHigh);
|
sl@0
|
117 |
}
|
sl@0
|
118 |
|
sl@0
|
119 |
|
sl@0
|
120 |
EXPORT_C void CScsServer::DisableShutdownTimer()
|
sl@0
|
121 |
/**
|
sl@0
|
122 |
The server will no longer shutdown after the last client session closes.
|
sl@0
|
123 |
Client calls to RScsClientBase::ShutdownServer will fail with KErrNotSupported.
|
sl@0
|
124 |
*/
|
sl@0
|
125 |
{
|
sl@0
|
126 |
if(iShutdownTimer)
|
sl@0
|
127 |
{
|
sl@0
|
128 |
iShutdownTimer->Cancel();
|
sl@0
|
129 |
}
|
sl@0
|
130 |
delete iShutdownTimer;
|
sl@0
|
131 |
iShutdownTimer = 0;
|
sl@0
|
132 |
}
|
sl@0
|
133 |
|
sl@0
|
134 |
EXPORT_C void CScsServer::EnableShutdownTimerL(TInt aShutdownPeriodUs)
|
sl@0
|
135 |
/**
|
sl@0
|
136 |
Enable shutdown timer support in the server.
|
sl@0
|
137 |
If there are currently no client sessions the timer will be immediately started, otherwise
|
sl@0
|
138 |
it will be started when the last client session closes.
|
sl@0
|
139 |
If the timer expires, before another client creates a session, the server will shutdown.
|
sl@0
|
140 |
The RScsClientBase::ShutdownServer api will now be supported, if called the server timeout
|
sl@0
|
141 |
will effectively be reduced to 0.
|
sl@0
|
142 |
*/
|
sl@0
|
143 |
{
|
sl@0
|
144 |
if(aShutdownPeriodUs <= 0)
|
sl@0
|
145 |
{
|
sl@0
|
146 |
return;
|
sl@0
|
147 |
}
|
sl@0
|
148 |
DisableShutdownTimer();
|
sl@0
|
149 |
iShutdownTimer = CShutdownTimer::NewL(aShutdownPeriodUs);
|
sl@0
|
150 |
if(iSessionCount == 0)
|
sl@0
|
151 |
{
|
sl@0
|
152 |
iShutdownTimer->Restart();
|
sl@0
|
153 |
}
|
sl@0
|
154 |
}
|
sl@0
|
155 |
|
sl@0
|
156 |
|
sl@0
|
157 |
EXPORT_C CScsServer::~CScsServer()
|
sl@0
|
158 |
/**
|
sl@0
|
159 |
Frees resources used at this level. Specifically, frees the
|
sl@0
|
160 |
container index, which is used to generate subsession containers,
|
sl@0
|
161 |
the shutdown timer, and the async request cleanup object.
|
sl@0
|
162 |
*/
|
sl@0
|
163 |
{
|
sl@0
|
164 |
__ASSERT_DEBUG(iSessionCount == 0, PanicServer(ESvrRemSessions));
|
sl@0
|
165 |
__ASSERT_DEBUG(iAsyncCleanup == 0 || !iAsyncCleanup->IsActive(), PanicServer(ESvrRemCleanup));
|
sl@0
|
166 |
__ASSERT_DEBUG(iAsyncRequests.Count() == 0, PanicServer(ESvrRemRequests));
|
sl@0
|
167 |
|
sl@0
|
168 |
delete iContainerIndex;
|
sl@0
|
169 |
delete iShutdownTimer;
|
sl@0
|
170 |
|
sl@0
|
171 |
delete iAsyncCleanup;
|
sl@0
|
172 |
iAsyncRequests.Reset();
|
sl@0
|
173 |
}
|
sl@0
|
174 |
|
sl@0
|
175 |
// -------- sessions --------
|
sl@0
|
176 |
|
sl@0
|
177 |
EXPORT_C CSession2* CScsServer::NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const
|
sl@0
|
178 |
/**
|
sl@0
|
179 |
Implement CServer2 by allocating a new session object. This function
|
sl@0
|
180 |
delegates the actual allocation to the subclass. Before creating the
|
sl@0
|
181 |
session object, it compares the requested version with its own version.
|
sl@0
|
182 |
After creating the session object, it increments the session count, which
|
sl@0
|
183 |
reset the shutdown timer if it is the only session.
|
sl@0
|
184 |
|
sl@0
|
185 |
@param aVersion Version of server which client requires.
|
sl@0
|
186 |
@param aMessage Connect message.
|
sl@0
|
187 |
@return New initialized instance of CSession2 subclass.
|
sl@0
|
188 |
*/
|
sl@0
|
189 |
{
|
sl@0
|
190 |
TBool versionOk = User::QueryVersionSupported(/* aCurrent */ iVersion, /* aRequested */ aVersion);
|
sl@0
|
191 |
if (! versionOk)
|
sl@0
|
192 |
User::Leave(KErrNotSupported);
|
sl@0
|
193 |
|
sl@0
|
194 |
CScsSession* s = const_cast<CScsServer*>(this)->DoNewSessionL(aMessage);
|
sl@0
|
195 |
|
sl@0
|
196 |
return s;
|
sl@0
|
197 |
}
|
sl@0
|
198 |
|
sl@0
|
199 |
EXPORT_C void CScsServer::DoPreHeapMarkOrCheckL()
|
sl@0
|
200 |
{
|
sl@0
|
201 |
}
|
sl@0
|
202 |
|
sl@0
|
203 |
EXPORT_C void CScsServer::DoPostHeapMarkOrCheckL()
|
sl@0
|
204 |
{
|
sl@0
|
205 |
}
|
sl@0
|
206 |
|
sl@0
|
207 |
void CScsServer::IncrementSessionCount()
|
sl@0
|
208 |
/**
|
sl@0
|
209 |
Record the fact that another session has been created. If this new
|
sl@0
|
210 |
session is the only session then cancel the shutdown timer.
|
sl@0
|
211 |
*/
|
sl@0
|
212 |
{
|
sl@0
|
213 |
++iSessionCount;
|
sl@0
|
214 |
if (iSessionCount == 1)
|
sl@0
|
215 |
{
|
sl@0
|
216 |
if(iShutdownTimer)
|
sl@0
|
217 |
{
|
sl@0
|
218 |
iShutdownTimer->Cancel();
|
sl@0
|
219 |
}
|
sl@0
|
220 |
}
|
sl@0
|
221 |
}
|
sl@0
|
222 |
|
sl@0
|
223 |
void CScsServer::DecrementSessionCount()
|
sl@0
|
224 |
/**
|
sl@0
|
225 |
Record the fact that a session has been deleted. If this was the
|
sl@0
|
226 |
only remaining session then start the shutdown timer.
|
sl@0
|
227 |
|
sl@0
|
228 |
Note the shutdown timer may be deferred if a request cleanup is
|
sl@0
|
229 |
pending.
|
sl@0
|
230 |
*/
|
sl@0
|
231 |
{
|
sl@0
|
232 |
--iSessionCount;
|
sl@0
|
233 |
if (iShutdownTimer && (iSessionCount == 0) && (! iAsyncCleanup->IsActive()))
|
sl@0
|
234 |
{
|
sl@0
|
235 |
iShutdownTimer->Restart();
|
sl@0
|
236 |
}
|
sl@0
|
237 |
}
|
sl@0
|
238 |
|
sl@0
|
239 |
EXPORT_C void CScsServer::ShutdownWhenIdleL()
|
sl@0
|
240 |
/**
|
sl@0
|
241 |
Shutdown immediately when server is next idle. If the server
|
sl@0
|
242 |
is not transient (ie. has no shutdown timer), this call is
|
sl@0
|
243 |
prohibited and will leave with KErrNotSupported.
|
sl@0
|
244 |
*/
|
sl@0
|
245 |
{
|
sl@0
|
246 |
if(! iShutdownTimer)
|
sl@0
|
247 |
{
|
sl@0
|
248 |
// We do not allow shutdown of non-transient servers.
|
sl@0
|
249 |
User::Leave(KErrNotSupported);
|
sl@0
|
250 |
}
|
sl@0
|
251 |
|
sl@0
|
252 |
// Next time we are idle, shutdown immediately.
|
sl@0
|
253 |
iShutdownTimer->ImmediateTimeoutNextRestart();
|
sl@0
|
254 |
}
|
sl@0
|
255 |
|
sl@0
|
256 |
|
sl@0
|
257 |
|
sl@0
|
258 |
// -------- asynchronous requests --------
|
sl@0
|
259 |
|
sl@0
|
260 |
CAsyncRequest* CScsServer::FindAsyncRequest(
|
sl@0
|
261 |
CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
|
sl@0
|
262 |
/**
|
sl@0
|
263 |
Find the outstanding request which matches the supplied criteria.
|
sl@0
|
264 |
|
sl@0
|
265 |
@param aSession Session which hosts the request.
|
sl@0
|
266 |
@param aSubsession Subsession which hosts the request, NULL if
|
sl@0
|
267 |
the request is relative to a session.
|
sl@0
|
268 |
@param aFunction The function identifier, without any SCS code.
|
sl@0
|
269 |
@return The matching asynchronous request, NULL if not
|
sl@0
|
270 |
found.
|
sl@0
|
271 |
*/
|
sl@0
|
272 |
{
|
sl@0
|
273 |
TInt reqCount = iAsyncRequests.Count();
|
sl@0
|
274 |
for (TInt i = reqCount - 1; i >= 0; --i)
|
sl@0
|
275 |
{
|
sl@0
|
276 |
CAsyncRequest* req = iAsyncRequests[i];
|
sl@0
|
277 |
|
sl@0
|
278 |
if (req->iSession != aSession)
|
sl@0
|
279 |
continue;
|
sl@0
|
280 |
|
sl@0
|
281 |
if (req->iSubsession != aSubsession)
|
sl@0
|
282 |
continue;
|
sl@0
|
283 |
|
sl@0
|
284 |
if (req->iFunction != aFunction)
|
sl@0
|
285 |
continue;
|
sl@0
|
286 |
|
sl@0
|
287 |
return req;
|
sl@0
|
288 |
}
|
sl@0
|
289 |
|
sl@0
|
290 |
return 0; // request not found
|
sl@0
|
291 |
}
|
sl@0
|
292 |
|
sl@0
|
293 |
void CScsServer::AddAsyncRequestL(CAsyncRequest* aAsyncRequest)
|
sl@0
|
294 |
/**
|
sl@0
|
295 |
Add the supplied request to the server's collection.
|
sl@0
|
296 |
|
sl@0
|
297 |
@param aAsyncRequest Request to add. If this function succeeds
|
sl@0
|
298 |
then ownership has been transferred to the
|
sl@0
|
299 |
collection.
|
sl@0
|
300 |
*/
|
sl@0
|
301 |
{
|
sl@0
|
302 |
// ensure this session does not already have an outstanding request
|
sl@0
|
303 |
// for the same function
|
sl@0
|
304 |
CAsyncRequest* existReq = FindAsyncRequest(
|
sl@0
|
305 |
aAsyncRequest->iSession, aAsyncRequest->iSubsession,
|
sl@0
|
306 |
aAsyncRequest->iFunction);
|
sl@0
|
307 |
|
sl@0
|
308 |
if (existReq != 0)
|
sl@0
|
309 |
User::Leave(KErrScsAsyncAlreadyQueued);
|
sl@0
|
310 |
|
sl@0
|
311 |
iAsyncRequests.AppendL(aAsyncRequest);
|
sl@0
|
312 |
}
|
sl@0
|
313 |
|
sl@0
|
314 |
void CScsServer::CancelAsyncRequest(
|
sl@0
|
315 |
CScsSession* aSession, CScsSubsession* aSubsession, TInt aFunction)
|
sl@0
|
316 |
/**
|
sl@0
|
317 |
Cancels a specific (sub)session request in response to a client
|
sl@0
|
318 |
command. Also completes the client request.
|
sl@0
|
319 |
|
sl@0
|
320 |
CancelOutstandingRequest should be called when a (sub)session is closed.
|
sl@0
|
321 |
|
sl@0
|
322 |
@param aSession Session which hosts the request.
|
sl@0
|
323 |
@param aSubsession Subsession which hosts the request, NULL if
|
sl@0
|
324 |
the request is relative to a session.
|
sl@0
|
325 |
@param aFunction The function identifier, without any SCS code.
|
sl@0
|
326 |
*/
|
sl@0
|
327 |
{
|
sl@0
|
328 |
CAsyncRequest* req = FindAsyncRequest(aSession, aSubsession, aFunction);
|
sl@0
|
329 |
|
sl@0
|
330 |
// not an error if the request is not queued; could have been
|
sl@0
|
331 |
// completed before the cancel function was processed.
|
sl@0
|
332 |
if (req != 0)
|
sl@0
|
333 |
req->CancelCompleteAndMarkForDeletion();
|
sl@0
|
334 |
}
|
sl@0
|
335 |
|
sl@0
|
336 |
void CScsServer::CancelOutstandingRequests(CScsSession* aSession, TBool aCompleteClientRequests)
|
sl@0
|
337 |
/**
|
sl@0
|
338 |
Cancels and deletes all outstanding asynchronous requests associated
|
sl@0
|
339 |
with the supplied session or any of its subsessions. Does not complete
|
sl@0
|
340 |
the associated client requests.
|
sl@0
|
341 |
|
sl@0
|
342 |
This function should be called when a session is closed.
|
sl@0
|
343 |
CancelAsyncRequest should be called when a specific request is cancelled.
|
sl@0
|
344 |
|
sl@0
|
345 |
@param aSession Session which is being closed.
|
sl@0
|
346 |
@param aCompleteClientRequests Whether to complete the client-side requests
|
sl@0
|
347 |
with KErrCancel.
|
sl@0
|
348 |
*/
|
sl@0
|
349 |
{
|
sl@0
|
350 |
CancelOutstandingRequests(aSession, KWildSubsession, aCompleteClientRequests);
|
sl@0
|
351 |
}
|
sl@0
|
352 |
|
sl@0
|
353 |
void CScsServer::CancelOutstandingRequests(CScsSession* aSession, CScsSubsession* aSubsession, TBool aCompleteClientRequests)
|
sl@0
|
354 |
/**
|
sl@0
|
355 |
Cancels and deletes all outstanding asynchronous requests associated
|
sl@0
|
356 |
with the supplied session and subsession. This should be called when
|
sl@0
|
357 |
a session or subsession is closed.
|
sl@0
|
358 |
|
sl@0
|
359 |
As an exception, the user-side request is completed when a subsession is
|
sl@0
|
360 |
closed, else the request would not be completed until the session itself
|
sl@0
|
361 |
was destroyed.
|
sl@0
|
362 |
|
sl@0
|
363 |
CancelAsyncRequest should be called when a specific request is cancelled.
|
sl@0
|
364 |
|
sl@0
|
365 |
@param aSession Session which is being closed.
|
sl@0
|
366 |
@param aSubsession Subsession which is being closed. If this is
|
sl@0
|
367 |
KWildSubsession then a session is being closed so all of
|
sl@0
|
368 |
its subsession requests should be destroyed as well.
|
sl@0
|
369 |
@param aCompleteClientRequests Whether to complete the client-side requests
|
sl@0
|
370 |
with KErrCancel.
|
sl@0
|
371 |
*/
|
sl@0
|
372 |
{
|
sl@0
|
373 |
TBool wildSubsession = (aSubsession == KWildSubsession);
|
sl@0
|
374 |
|
sl@0
|
375 |
TInt reqCount = iAsyncRequests.Count();
|
sl@0
|
376 |
for (TInt i = reqCount - 1; i >= 0; --i)
|
sl@0
|
377 |
{
|
sl@0
|
378 |
CAsyncRequest* req = iAsyncRequests[i];
|
sl@0
|
379 |
|
sl@0
|
380 |
TBool sessionMatch = (req->iSession == aSession);
|
sl@0
|
381 |
if (! sessionMatch)
|
sl@0
|
382 |
continue;
|
sl@0
|
383 |
|
sl@0
|
384 |
TBool subsessionMatch = wildSubsession || (req->iSubsession == aSubsession);
|
sl@0
|
385 |
if (! subsessionMatch)
|
sl@0
|
386 |
continue;
|
sl@0
|
387 |
|
sl@0
|
388 |
if (aCompleteClientRequests)
|
sl@0
|
389 |
req->CancelCompleteAndMarkForDeletion();
|
sl@0
|
390 |
else
|
sl@0
|
391 |
{
|
sl@0
|
392 |
req->DoCleanup();
|
sl@0
|
393 |
req->MarkForDeletion();
|
sl@0
|
394 |
}
|
sl@0
|
395 |
}
|
sl@0
|
396 |
}
|
sl@0
|
397 |
|
sl@0
|
398 |
TInt CScsServer::RemoveCompletedRequests(TAny* aPtr)
|
sl@0
|
399 |
/**
|
sl@0
|
400 |
This static function is called when iAsyncCleanup
|
sl@0
|
401 |
runs. It interprets its argument as a pointer to
|
sl@0
|
402 |
an instance of CScsServer and removes any asynchronous
|
sl@0
|
403 |
requests which have been completed.
|
sl@0
|
404 |
|
sl@0
|
405 |
@param aPtr Required callback argument. Interpreted
|
sl@0
|
406 |
as a pointer to an instance of CScsServer.
|
sl@0
|
407 |
@return KErrNone. Required to satisfy the TCallBack
|
sl@0
|
408 |
function signature.
|
sl@0
|
409 |
@see RemoveCompletedRequests()
|
sl@0
|
410 |
*/
|
sl@0
|
411 |
{
|
sl@0
|
412 |
CScsServer* svr = static_cast<CScsServer*>(aPtr);
|
sl@0
|
413 |
svr->RemoveCompletedRequests();
|
sl@0
|
414 |
return KErrNone;
|
sl@0
|
415 |
}
|
sl@0
|
416 |
|
sl@0
|
417 |
void CScsServer::RemoveCompletedRequests()
|
sl@0
|
418 |
/**
|
sl@0
|
419 |
Delete any asynchronous requests which are marked for deletion.
|
sl@0
|
420 |
*/
|
sl@0
|
421 |
{
|
sl@0
|
422 |
// The requests have already been completed; they just need to be removed.
|
sl@0
|
423 |
TInt reqCount = iAsyncRequests.Count();
|
sl@0
|
424 |
for (TInt i = reqCount - 1; i >= 0; --i)
|
sl@0
|
425 |
{
|
sl@0
|
426 |
CAsyncRequest* req = iAsyncRequests[i];
|
sl@0
|
427 |
if (req->iSession != 0) // still outstanding if iSession != 0
|
sl@0
|
428 |
continue;
|
sl@0
|
429 |
|
sl@0
|
430 |
delete req;
|
sl@0
|
431 |
iAsyncRequests.Remove(i);
|
sl@0
|
432 |
}
|
sl@0
|
433 |
|
sl@0
|
434 |
// if no more outstanding requests then reset array so heap balances
|
sl@0
|
435 |
if (iAsyncRequests.Count() == 0)
|
sl@0
|
436 |
iAsyncRequests.Compress();
|
sl@0
|
437 |
|
sl@0
|
438 |
// if the shutdown timer was deferred because of an impending
|
sl@0
|
439 |
// cleanup then launch it now.
|
sl@0
|
440 |
if (iShutdownTimer && (iSessionCount == 0))
|
sl@0
|
441 |
{
|
sl@0
|
442 |
iShutdownTimer->Restart();
|
sl@0
|
443 |
}
|
sl@0
|
444 |
}
|
sl@0
|
445 |
// End of file
|
sl@0
|
446 |
|