|
1 /* |
|
2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: subsession class for operations related to local access. |
|
15 * |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include <e32base.h> |
|
21 #include <s32mem.h> |
|
22 |
|
23 #include <epos_poslmdatabaseutility.h> |
|
24 #include <epos_cposlmdiskutilities.h> |
|
25 #include <epos_cposlmlocaldbaccess.h> |
|
26 |
|
27 #include "epos_lmdebug.h" |
|
28 #include "EPos_CPosLmServer.h" |
|
29 #include "EPos_CPosLmOperationManager.h" |
|
30 #include "EPos_PosLmServerCommon.h" |
|
31 #include "EPos_LmServerGlobal.h" |
|
32 #include "EPos_LandmarksServerPanics.h" |
|
33 #include "EPos_CPosLmEventHandler.h" |
|
34 #include "EPos_PosLmDatabaseManager.h" |
|
35 #include "epos_cposlmindexmanager.h" |
|
36 #include "EPos_CPosLmNameIndex.h" |
|
37 #include "EPos_CPosLmActiveCompacter.h" |
|
38 #include "EPos_CPosLmLocalAccessSubsession.h" |
|
39 |
|
40 // ----------------------------------------------------------------------------- |
|
41 // ----------------------------------------------------------------------------- |
|
42 // |
|
43 CPosLmLocalAccessSubsession::CPosLmLocalAccessSubsession( |
|
44 CPosLmServer* aLmServer) : |
|
45 CPosLmSubsessionBase(EPosLocalAccessSubsession, aLmServer) |
|
46 { |
|
47 } |
|
48 |
|
49 // ----------------------------------------------------------------------------- |
|
50 // ----------------------------------------------------------------------------- |
|
51 // |
|
52 void CPosLmLocalAccessSubsession::ConstructL() |
|
53 { |
|
54 } |
|
55 |
|
56 // ----------------------------------------------------------------------------- |
|
57 // ----------------------------------------------------------------------------- |
|
58 // |
|
59 CPosLmLocalAccessSubsession* CPosLmLocalAccessSubsession::NewLC( |
|
60 CPosLmServer* aLmServer) |
|
61 { |
|
62 CPosLmLocalAccessSubsession* self = |
|
63 new (ELeave) CPosLmLocalAccessSubsession(aLmServer); |
|
64 CleanupClosePushL(*self); |
|
65 self->ConstructL(); |
|
66 return self; |
|
67 } |
|
68 |
|
69 // ----------------------------------------------------------------------------- |
|
70 // ----------------------------------------------------------------------------- |
|
71 // |
|
72 CPosLmLocalAccessSubsession::~CPosLmLocalAccessSubsession() |
|
73 { |
|
74 delete iCompacter; |
|
75 delete iDbAccess; |
|
76 delete iEventHandler; |
|
77 |
|
78 // release database |
|
79 iHasWriteLock = EFalse; |
|
80 iNoOfReadLocks = 0; |
|
81 if ( iUsingNameIndex && Server() && iDbUri ) |
|
82 { |
|
83 Server()->IndexManager().RemoveIndexUser( *iDbUri ); |
|
84 iUsingNameIndex = EFalse; |
|
85 } |
|
86 delete iDbUri; |
|
87 } |
|
88 |
|
89 // ----------------------------------------------------------------------------- |
|
90 // ----------------------------------------------------------------------------- |
|
91 // |
|
92 TBool CPosLmLocalAccessSubsession::HasWriteLock( const TDesC& aUri ) |
|
93 { |
|
94 if (iHasWriteLock && aUri == *iDbUri) |
|
95 { |
|
96 return ETrue; |
|
97 } |
|
98 |
|
99 return EFalse; |
|
100 } |
|
101 |
|
102 // ----------------------------------------------------------------------------- |
|
103 // ----------------------------------------------------------------------------- |
|
104 // |
|
105 TBool CPosLmLocalAccessSubsession::HasAnyLock( const TDesC& aUri ) |
|
106 { |
|
107 if ((iHasWriteLock || iNoOfReadLocks > 0) && aUri == *iDbUri) |
|
108 { |
|
109 return ETrue; |
|
110 } |
|
111 |
|
112 return EFalse; |
|
113 } |
|
114 |
|
115 // ----------------------------------------------------------------------------- |
|
116 // ----------------------------------------------------------------------------- |
|
117 // |
|
118 void CPosLmLocalAccessSubsession::HandleOperationEventL( |
|
119 TPosLmEvent aEvent, |
|
120 const TDesC& aUri, |
|
121 TBool aCheckUri) |
|
122 { |
|
123 // Check if the event is dedicated to the database, which this subsession is |
|
124 // connected to. |
|
125 if (!aCheckUri && iEventHandler && iDbUri || |
|
126 iEventHandler && iDbUri && aUri.Compare(*iDbUri) == 0) |
|
127 { |
|
128 iEventHandler->HandleIncomingEventL(aEvent); |
|
129 } |
|
130 } |
|
131 |
|
132 // ----------------------------------------------------------------------------- |
|
133 // ----------------------------------------------------------------------------- |
|
134 // |
|
135 void CPosLmLocalAccessSubsession::CompleteOutstandingEventRequest( |
|
136 TInt aError) |
|
137 { |
|
138 if (iEventHandler) |
|
139 { |
|
140 iEventHandler->CompleteAnyOutStandingRequest(aError); |
|
141 } |
|
142 } |
|
143 |
|
144 // ----------------------------------------------------------------------------- |
|
145 // ----------------------------------------------------------------------------- |
|
146 // |
|
147 void CPosLmLocalAccessSubsession::ReleaseCompactLock() |
|
148 { |
|
149 delete iCompacter; |
|
150 iCompacter = NULL; |
|
151 iHasWriteLock = EFalse; |
|
152 } |
|
153 |
|
154 // ----------------------------------------------------------------------------- |
|
155 // ----------------------------------------------------------------------------- |
|
156 // |
|
157 void CPosLmLocalAccessSubsession::ServiceL( |
|
158 const RMessage2& aMessage) |
|
159 { |
|
160 #if 0 // #ifdef _DEBUG |
|
161 RThread client; |
|
162 aMessage.Client( client ); |
|
163 LOG3("LocalSession::ServiceL in: function %d (client SID 0x%X, thread 0x%X)", |
|
164 aMessage.Function(), aMessage.SecureId().iId, client.Id() ); |
|
165 #endif |
|
166 |
|
167 switch (aMessage.Function()) |
|
168 { |
|
169 case EPosLmServerRegisterSession: |
|
170 if (iDbUri) |
|
171 { |
|
172 PanicClient(aMessage, EPosClientHasAlreadyRegistered); |
|
173 return; |
|
174 } |
|
175 RegisterUriL(aMessage); |
|
176 break; |
|
177 case EPosLmServerInitializeSync: |
|
178 case EPosLmServerInitializeAsync: |
|
179 case EPosLmServerInitializeCancel: |
|
180 case EPosLmServerLangSwitchSync: |
|
181 case EPosLmServerLangSwitchAsync: |
|
182 case EPosLmServerLangSwitchCancel: |
|
183 case EPosLmServerRecoverSync: |
|
184 case EPosLmServerRecoverAsync: |
|
185 case EPosLmServerRecoverCancel: |
|
186 if (!iDbUri) |
|
187 { |
|
188 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
189 return; |
|
190 } |
|
191 Server()->OperationManagerL(aMessage.Function())->AddRequestL( |
|
192 aMessage, *iDbUri, this); |
|
193 break; |
|
194 case EPosLmServerDbLock: |
|
195 if (!iDbUri) |
|
196 { |
|
197 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
198 return; |
|
199 } |
|
200 DatabaseLockL(aMessage); |
|
201 break; |
|
202 case EPosLmServerIndexTransaction: |
|
203 if (!iDbUri) |
|
204 { |
|
205 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
206 return; |
|
207 } |
|
208 HandleDataTransactionL(aMessage); |
|
209 break; |
|
210 case EPosLmServerReportLmEvent: |
|
211 if (!iDbUri) |
|
212 { |
|
213 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
214 return; |
|
215 } |
|
216 ForwardEventToAllSessionsL(aMessage); |
|
217 break; |
|
218 case EPosLmServerUpdateNameIndex: |
|
219 if (!iDbUri) |
|
220 { |
|
221 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
222 return; |
|
223 } |
|
224 HandleUpdateLandmarkIndexL( aMessage ); |
|
225 break; |
|
226 case EPosLmServerListenForLmEvent: |
|
227 // No check of iDbUri needed here |
|
228 User::LeaveIfError(Server()->StartSettingsListenerIfNeeded()); |
|
229 if (!iEventHandler) |
|
230 { |
|
231 iEventHandler = CPosLmEventHandler::NewL(); |
|
232 } |
|
233 iEventHandler->HandleRequestForEventL(aMessage); |
|
234 break; |
|
235 case EPosLmServerCancelListenForLmEvent: |
|
236 // No check of iDbUri needed here |
|
237 delete iEventHandler; |
|
238 iEventHandler = NULL; |
|
239 LmServerGlobal::Complete(aMessage, KErrNone); |
|
240 break; |
|
241 case EPosLmServerCreateDefaultDb: |
|
242 // No check of iDbUri needed here |
|
243 CreateDefaultDatabaseL(aMessage); |
|
244 break; |
|
245 case EPosLmServerOpenNameIndex: |
|
246 case EPosLmServerCloseNameIndex: |
|
247 if ( !iDbUri ) |
|
248 { |
|
249 PanicClient( aMessage, EPosClientHasNotRegistered ); |
|
250 return; |
|
251 } |
|
252 HandleUseNameIndexL( aMessage ); |
|
253 break; |
|
254 case EPosLmServerReadSortedIds: |
|
255 if (!iDbUri) |
|
256 { |
|
257 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
258 return; |
|
259 } |
|
260 HandleReadSortedIdsL( aMessage ); |
|
261 break; |
|
262 case EPosLmServerReadNameIndex: |
|
263 if (!iDbUri) |
|
264 { |
|
265 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
266 return; |
|
267 } |
|
268 HandleReadSortedLandmarksL( aMessage ); |
|
269 break; |
|
270 case EPosLmServerNameIndexStatus: |
|
271 if (!iDbUri) |
|
272 { |
|
273 PanicClient(aMessage, EPosClientHasNotRegistered); |
|
274 return; |
|
275 } |
|
276 HandleNameIndexStatusL( aMessage ); |
|
277 break; |
|
278 default: |
|
279 User::Leave(KErrNotSupported); |
|
280 break; |
|
281 } |
|
282 #if 0 // #ifdef _DEBUG |
|
283 LOG("LocalSession::ServiceL out"); |
|
284 #endif |
|
285 } |
|
286 |
|
287 // ----------------------------------------------------------------------------- |
|
288 // ----------------------------------------------------------------------------- |
|
289 // |
|
290 void CPosLmLocalAccessSubsession::RegisterUriL( |
|
291 const RMessage2& aMessage) |
|
292 { |
|
293 // Validate length of client message. |
|
294 TInt desLength = aMessage.GetDesLength(KPosLmServerUriArg); |
|
295 if (desLength < 0) |
|
296 { |
|
297 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
298 return; |
|
299 } |
|
300 |
|
301 // Read URI from client message. |
|
302 HBufC* dbUri = HBufC::NewLC(desLength); |
|
303 TPtr uriPtr = dbUri->Des(); |
|
304 if (LmServerGlobal::Read(aMessage, KPosLmServerUriArg, uriPtr) != KErrNone) |
|
305 { |
|
306 CleanupStack::PopAndDestroy(dbUri); |
|
307 return; |
|
308 } |
|
309 |
|
310 // Lowercase the URI to be able to match different cases of the same URI. |
|
311 uriPtr.LowerCase(); |
|
312 |
|
313 TInt err = PosLmDatabaseUtility::ValidateDatabaseUri(uriPtr); |
|
314 if (err == KErrArgument) |
|
315 { |
|
316 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
317 CleanupStack::PopAndDestroy(dbUri); |
|
318 return; |
|
319 } |
|
320 else |
|
321 { |
|
322 User::LeaveIfError(err); |
|
323 } |
|
324 |
|
325 // iDbUri is set last as it is used to validate if the uri has been |
|
326 // registered properly. |
|
327 CleanupStack::Pop(dbUri); |
|
328 iDbUri = dbUri; |
|
329 |
|
330 LmServerGlobal::Complete(aMessage, KErrNone); |
|
331 } |
|
332 |
|
333 // ----------------------------------------------------------------------------- |
|
334 // ----------------------------------------------------------------------------- |
|
335 // |
|
336 void CPosLmLocalAccessSubsession::DatabaseLockL( |
|
337 const RMessage2& aMessage) |
|
338 { |
|
339 TBool setLockOn = static_cast<TBool>(aMessage.Int0()); |
|
340 TBool writeLock = static_cast<TBool>(aMessage.Int1()); |
|
341 |
|
342 if (setLockOn) |
|
343 { |
|
344 if (!Server()->CanAcquireLock(writeLock, *iDbUri)) |
|
345 { |
|
346 User::Leave(KErrLocked); |
|
347 } |
|
348 |
|
349 if (writeLock) |
|
350 { |
|
351 iHasWriteLock = ETrue; |
|
352 } |
|
353 else |
|
354 { |
|
355 iNoOfReadLocks++; |
|
356 } |
|
357 } |
|
358 else if (writeLock) |
|
359 { |
|
360 if (!iHasWriteLock) |
|
361 { |
|
362 PanicClient(aMessage, EPosLmDbNotLocked); |
|
363 return; |
|
364 } |
|
365 iHasWriteLock = EFalse; |
|
366 } |
|
367 else |
|
368 { |
|
369 if (iNoOfReadLocks == 0) |
|
370 { |
|
371 PanicClient(aMessage, EPosLmDbNotLocked); |
|
372 return; |
|
373 } |
|
374 iNoOfReadLocks--; |
|
375 } |
|
376 |
|
377 LmServerGlobal::Complete(aMessage, KErrNone); |
|
378 |
|
379 if (!setLockOn && writeLock) // releasing write lock |
|
380 { |
|
381 TRAP_IGNORE( CompactIfNeededL() ); |
|
382 } |
|
383 } |
|
384 |
|
385 // ----------------------------------------------------------------------------- |
|
386 // ----------------------------------------------------------------------------- |
|
387 // |
|
388 void CPosLmLocalAccessSubsession::HandleDataTransactionL( const RMessage2& aMessage ) |
|
389 { |
|
390 if ( Server()->IndexManager().Find( *iDbUri ) >= 0 ) |
|
391 { |
|
392 CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri ); |
|
393 User::LeaveIfError( index.Status() ); |
|
394 switch( aMessage.Int0() ) |
|
395 { |
|
396 case EPosLmServerTransactionStart: |
|
397 index.StartTransaction(); |
|
398 break; |
|
399 case EPosLmServerTransactionCommit: |
|
400 index.CommitTransaction(); |
|
401 break; |
|
402 case EPosLmServerTransactionRollback: |
|
403 index.RollbackTransaction(); |
|
404 break; |
|
405 default: |
|
406 PanicClient( aMessage, EPosUnableToReadOrWriteDataToClient ); |
|
407 } |
|
408 } |
|
409 |
|
410 LmServerGlobal::Complete( aMessage, KErrNone ); |
|
411 } |
|
412 |
|
413 // ----------------------------------------------------------------------------- |
|
414 // ----------------------------------------------------------------------------- |
|
415 // |
|
416 void CPosLmLocalAccessSubsession::ForwardEventToAllSessionsL( |
|
417 const RMessage2& aMessage) |
|
418 { |
|
419 TPckgBuf<TPosLmEvent> event; |
|
420 |
|
421 TInt desLength = aMessage.GetDesLength(KPosLmServerEventArg); |
|
422 if (desLength != event.Length()) |
|
423 { |
|
424 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
425 return; |
|
426 } |
|
427 |
|
428 if (LmServerGlobal::Read(aMessage, KPosLmServerEventArg, event) != KErrNone) |
|
429 { |
|
430 return; |
|
431 } |
|
432 |
|
433 // Validate that the event type is a valid enum value. |
|
434 TPosLmEventType eventType = event().iEventType; |
|
435 if (!(eventType == EPosLmEventUnknownChanges || |
|
436 eventType == EPosLmEventNewDefaultDatabaseLocation || |
|
437 eventType == EPosLmEventMediaRemoved || |
|
438 (eventType >= EPosLmEventLandmarkUnknownChanges && |
|
439 eventType <= EPosLmEventLandmarkUpdated) || |
|
440 (eventType >= EPosLmEventCategoryUnknownChanges && |
|
441 eventType <= EPosLmEventCategoryUpdated))) |
|
442 { |
|
443 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
444 return; |
|
445 } |
|
446 |
|
447 Server()->ForwardEventToAllSessionsL(event(), *iDbUri, ETrue); |
|
448 |
|
449 LmServerGlobal::Complete(aMessage, KErrNone); |
|
450 } |
|
451 |
|
452 // ----------------------------------------------------------------------------- |
|
453 // ----------------------------------------------------------------------------- |
|
454 // |
|
455 void CPosLmLocalAccessSubsession::CreateDefaultDatabaseL( |
|
456 const RMessage2& aMessage) |
|
457 { |
|
458 TInt desLength = aMessage.GetDesLength(KPosLmServerUriArg); |
|
459 if (desLength < 0) |
|
460 { |
|
461 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
462 return; |
|
463 } |
|
464 |
|
465 HBufC* msgUri = HBufC::NewLC(desLength); |
|
466 TPtr uriPtr = msgUri->Des(); |
|
467 |
|
468 if (LmServerGlobal::Read(aMessage, KPosLmServerUriArg, uriPtr) == KErrNone) |
|
469 { |
|
470 HBufC* uri = PosLmDatabaseUtility::CreateDatabaseUriL(*msgUri); |
|
471 CleanupStack::PushL(uri); |
|
472 |
|
473 // To remove a warning, the event must be default constructed. |
|
474 TPosLmDatabaseEvent event = |
|
475 { |
|
476 EPosLmDbDatabaseRegistered, |
|
477 {0,0,0,0,0,0,0,0} |
|
478 }; |
|
479 |
|
480 CheckDiskSizeL(*uri); |
|
481 TPckgBuf<TBool> replaceDb; |
|
482 |
|
483 desLength = aMessage.GetDesLength(KPosLmServerDbReplaceArg); |
|
484 if (desLength != replaceDb.Length()) |
|
485 { |
|
486 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
487 CleanupStack::PopAndDestroy(2, msgUri); |
|
488 return; |
|
489 } |
|
490 |
|
491 if (LmServerGlobal::Read( |
|
492 aMessage, KPosLmServerDbReplaceArg, replaceDb) != KErrNone) |
|
493 { |
|
494 CleanupStack::PopAndDestroy(2, msgUri); |
|
495 return; |
|
496 } |
|
497 |
|
498 PosLmDatabaseManager::CreateDatabaseL(uri->Des(), ETrue, replaceDb()); |
|
499 |
|
500 Server()->ForwardEventToAllSessionsL(event, uri->Des()); |
|
501 LmServerGlobal::Complete(aMessage, KErrNone); |
|
502 CleanupStack::PopAndDestroy(uri); |
|
503 } |
|
504 |
|
505 CleanupStack::PopAndDestroy(msgUri); |
|
506 } |
|
507 |
|
508 // ----------------------------------------------------------------------------- |
|
509 // ----------------------------------------------------------------------------- |
|
510 // |
|
511 void CPosLmLocalAccessSubsession::CheckDiskSizeL( |
|
512 const TDesC& aUri) |
|
513 { |
|
514 CPosLmDiskUtilities* diskUtilities = CPosLmDiskUtilities::NewL(); |
|
515 CleanupStack::PushL(diskUtilities); |
|
516 |
|
517 diskUtilities->DiskSpaceBelowCriticalLevelL( |
|
518 diskUtilities->EstimatedDiskSizeOfEmptyDatabase(), |
|
519 (aUri)[KPosLocalDbFileProtocol().Length()]); |
|
520 |
|
521 CleanupStack::PopAndDestroy(diskUtilities); |
|
522 } |
|
523 |
|
524 // ----------------------------------------------------------------------------- |
|
525 // ----------------------------------------------------------------------------- |
|
526 // |
|
527 void CPosLmLocalAccessSubsession::CompactIfNeededL() |
|
528 { |
|
529 if (!iDbAccess) |
|
530 { |
|
531 CPosLmLocalDbAccess* dbAccess = |
|
532 CPosLmLocalDbAccess::NewL(CPosLmLocalDbAccess::EServerCompactLevel); |
|
533 CleanupStack::PushL(dbAccess); |
|
534 User::LeaveIfError(dbAccess->OpenDatabaseL(*iDbUri)); // Will be trapped |
|
535 CleanupStack::Pop(dbAccess); |
|
536 iDbAccess = dbAccess; |
|
537 } |
|
538 |
|
539 if (iDbAccess->IsCompactNeededL()) |
|
540 { |
|
541 iCompacter = CPosLmActiveCompacter::NewL(*this, *iDbAccess); |
|
542 iHasWriteLock = ETrue; |
|
543 } |
|
544 } |
|
545 |
|
546 // ----------------------------------------------------------------------------- |
|
547 // ----------------------------------------------------------------------------- |
|
548 // |
|
549 void CPosLmLocalAccessSubsession::HandleReadSortedIdsL( const RMessage2& aMessage ) |
|
550 { |
|
551 AssertIndexLoadedL(); |
|
552 |
|
553 TPosLmServerReadArrayParam param; |
|
554 TPckg<TPosLmServerReadArrayParam> pack( param ); |
|
555 if ( LmServerGlobal::Read( aMessage, KPosLmServerIdArrayParam, pack ) != KErrNone ) |
|
556 { |
|
557 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
558 return; |
|
559 } |
|
560 |
|
561 CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri ); |
|
562 User::LeaveIfError( index.Status() ); |
|
563 |
|
564 TPosLmItemId* ids = new (ELeave) TPosLmItemId[ param.iCount ]; |
|
565 CleanupStack::PushL( ids ); |
|
566 TPtrC8 data( (TUint8*) ids, sizeof( TPosLmItemId ) * param.iCount ); |
|
567 |
|
568 TInt count = index.GetSortedIds( param.iFirst, param.iCount, ids, param.iRemainder ); |
|
569 if ( count >= 0 ) |
|
570 { |
|
571 param.iActualCount = count; |
|
572 param.iMinBufferNeeded = 0; |
|
573 User::LeaveIfError( LmServerGlobal::Write( aMessage, KPosLmServerIdArrayParam, pack ) ); |
|
574 User::LeaveIfError( LmServerGlobal::Write( aMessage, KPosLmServerIdArray, data ) ); |
|
575 } |
|
576 else |
|
577 { |
|
578 User::Leave( count ); // error code |
|
579 } |
|
580 CleanupStack::PopAndDestroy( ids ); |
|
581 LmServerGlobal::Complete( aMessage, count ); |
|
582 } |
|
583 |
|
584 // ----------------------------------------------------------------------------- |
|
585 // ----------------------------------------------------------------------------- |
|
586 // |
|
587 void CPosLmLocalAccessSubsession::HandleReadSortedLandmarksL( const RMessage2& aMessage ) |
|
588 { |
|
589 AssertIndexLoadedL(); |
|
590 |
|
591 TPosLmServerReadArrayParam param; |
|
592 TPckg<TPosLmServerReadArrayParam> pack( param ); |
|
593 if ( LmServerGlobal::Read( aMessage, 0, pack ) != KErrNone ) |
|
594 { |
|
595 PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient); |
|
596 return; |
|
597 } |
|
598 |
|
599 param.iMinBufferNeeded = 0; |
|
600 param.iActualCount = 0; |
|
601 param.iRemainder = 0; |
|
602 |
|
603 TInt bufferSize = aMessage.GetDesLengthL( 1 ); |
|
604 |
|
605 CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri ); |
|
606 User::LeaveIfError( index.Status() ); |
|
607 |
|
608 CBufFlat* buffer = CBufFlat::NewL( bufferSize ); |
|
609 CleanupStack::PushL( buffer ); |
|
610 |
|
611 RBufWriteStream out; |
|
612 out.Open( *buffer ); |
|
613 CleanupClosePushL( out ); |
|
614 |
|
615 if ( param.iCount > 0 ) // in ascending order |
|
616 { |
|
617 GetSortedLandmarksL( index, out, param, bufferSize ); |
|
618 } |
|
619 else |
|
620 { |
|
621 GetSortedLandmarksReverseL( index, out, param, bufferSize ); |
|
622 } |
|
623 |
|
624 out.CommitL(); |
|
625 |
|
626 User::LeaveIfError( LmServerGlobal::Write( aMessage, 0, pack ) ); |
|
627 User::LeaveIfError( LmServerGlobal::Write( aMessage, 1, buffer->Ptr( 0 ) ) ); |
|
628 LmServerGlobal::Complete( aMessage, KErrNone ); |
|
629 |
|
630 CleanupStack::PopAndDestroy( &out ); |
|
631 CleanupStack::PopAndDestroy( buffer ); |
|
632 } |
|
633 |
|
634 // ----------------------------------------------------------------------------- |
|
635 // ----------------------------------------------------------------------------- |
|
636 // |
|
637 void CPosLmLocalAccessSubsession::GetSortedLandmarksL( |
|
638 CPosLmNameIndex& aNameIndex, |
|
639 RWriteStream& aOut, |
|
640 TPosLmServerReadArrayParam& aParam, |
|
641 TInt aMaxSize ) |
|
642 { |
|
643 TInt start = Max( aParam.iFirst, 0 ); |
|
644 TInt last = Min( aParam.iFirst + aParam.iCount, aNameIndex.Count() ); |
|
645 |
|
646 TInt leftInBuffer = aMaxSize; |
|
647 TInt i = start; |
|
648 for ( ; i < last ; i++ ) |
|
649 { |
|
650 const CPosLmNameIndex::CItem& item = aNameIndex.Item( i ); |
|
651 if ( !ExportIndexItemL( item, aOut, leftInBuffer, aParam ) ) |
|
652 break; |
|
653 } |
|
654 |
|
655 aParam.iRemainder = aNameIndex.Count() - i; |
|
656 } |
|
657 |
|
658 // ----------------------------------------------------------------------------- |
|
659 // ----------------------------------------------------------------------------- |
|
660 // |
|
661 void CPosLmLocalAccessSubsession::GetSortedLandmarksReverseL( |
|
662 CPosLmNameIndex& aNameIndex, |
|
663 RWriteStream& aOut, |
|
664 TPosLmServerReadArrayParam& aParam, |
|
665 TInt aMaxSize ) |
|
666 { |
|
667 TInt start = Min( aParam.iFirst, aNameIndex.Count() - 1 ); |
|
668 TInt last = Max( aParam.iFirst + aParam.iCount, -1 ); // iCount is negative |
|
669 |
|
670 TInt leftInBuffer = aMaxSize; |
|
671 TInt i = start; |
|
672 for ( ; i > last ; i-- ) |
|
673 { |
|
674 const CPosLmNameIndex::CItem& item = aNameIndex.Item( i ); |
|
675 if ( !ExportIndexItemL( item, aOut, leftInBuffer, aParam ) ) |
|
676 break; |
|
677 } |
|
678 |
|
679 aParam.iRemainder = i+1; |
|
680 } |
|
681 |
|
682 // ----------------------------------------------------------------------------- |
|
683 // ----------------------------------------------------------------------------- |
|
684 // |
|
685 TBool CPosLmLocalAccessSubsession::ExportIndexItemL( |
|
686 const CPosLmNameIndex::CItem& aItem, |
|
687 RWriteStream& aOut, |
|
688 TInt& aLeftInBuffer, |
|
689 TPosLmServerReadArrayParam& aParam ) |
|
690 { |
|
691 TInt itemSize = aItem.Size(); |
|
692 if ( itemSize <= aLeftInBuffer ) |
|
693 { |
|
694 aItem.ExternalizeL( aOut ); |
|
695 aLeftInBuffer -= itemSize; |
|
696 aParam.iActualCount++; |
|
697 return ETrue; |
|
698 } |
|
699 else |
|
700 { |
|
701 if ( itemSize > aLeftInBuffer ) |
|
702 { |
|
703 aParam.iMinBufferNeeded = itemSize; |
|
704 } |
|
705 return EFalse; |
|
706 } |
|
707 } |
|
708 |
|
709 // ----------------------------------------------------------------------------- |
|
710 // ----------------------------------------------------------------------------- |
|
711 // |
|
712 void CPosLmLocalAccessSubsession::HandleUpdateLandmarkIndexL( const RMessage2& aMessage ) |
|
713 { |
|
714 //LOG1("UpdateIndex: function %d", aMessage.Int0() ); |
|
715 AssertIndexLoadedL(); |
|
716 switch ( aMessage.Int0() ) |
|
717 { |
|
718 case EPosLmServerAddLandmarks: |
|
719 case EPosLmServerUpdateLandmarks: |
|
720 HandleLandmarksAddedOrUpdatedL( aMessage ); |
|
721 break; |
|
722 case EPosLmServerRemoveLandmarks: |
|
723 HandleLandmarksRemovedL( aMessage ); |
|
724 break; |
|
725 default: |
|
726 break; |
|
727 } |
|
728 } |
|
729 |
|
730 // ----------------------------------------------------------------------------- |
|
731 // ----------------------------------------------------------------------------- |
|
732 // |
|
733 void CPosLmLocalAccessSubsession::HandleLandmarksAddedOrUpdatedL( const RMessage2& aMessage ) |
|
734 { |
|
735 CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri ); |
|
736 User::LeaveIfError( index.Status() ); |
|
737 |
|
738 HBufC8* buf = LmServerGlobal::CopyClientBuffer8LC( aMessage, 1 ); |
|
739 RDesReadStream readStream( *buf ); |
|
740 |
|
741 TPosLmItemId id = KPosLmNullItemId; |
|
742 |
|
743 // Update index |
|
744 TInt lmCount = readStream.ReadInt32L(); |
|
745 for ( TInt i = 0; i < lmCount; i++ ) |
|
746 { |
|
747 id = readStream.ReadInt32L(); |
|
748 TInt nameLen = readStream.ReadInt32L(); |
|
749 |
|
750 HBufC* lmBuf = HBufC::NewLC( nameLen ); |
|
751 |
|
752 TPtr name( lmBuf->Des() ); |
|
753 readStream.ReadL( name, nameLen ); |
|
754 |
|
755 if ( aMessage.Int0() == EPosLmServerUpdateLandmarks ) |
|
756 { |
|
757 index.UpdateL( id, lmBuf ); |
|
758 } |
|
759 else |
|
760 { |
|
761 index.InsertL( id, lmBuf ); |
|
762 } |
|
763 CleanupStack::Pop( lmBuf ); |
|
764 } |
|
765 |
|
766 readStream.Close(); |
|
767 CleanupStack::PopAndDestroy( buf ); |
|
768 |
|
769 LmServerGlobal::Complete( aMessage, KErrNone ); |
|
770 } |
|
771 |
|
772 // ----------------------------------------------------------------------------- |
|
773 // ----------------------------------------------------------------------------- |
|
774 // |
|
775 void CPosLmLocalAccessSubsession::HandleLandmarksRemovedL( const RMessage2& aMessage ) |
|
776 { |
|
777 HBufC8* buf = LmServerGlobal::CopyClientBuffer8LC( aMessage, 1 ); |
|
778 if ( buf->Size() % ( sizeof( TPosLmItemId ) ) != 0 ) |
|
779 { |
|
780 User::Leave( KErrArgument ); |
|
781 } |
|
782 |
|
783 TInt lmCount = buf->Size() / ( sizeof( TPosLmItemId ) ); |
|
784 const TPosLmItemId* ids = reinterpret_cast<const TPosLmItemId*>( buf->Ptr() ); |
|
785 |
|
786 // Update index |
|
787 CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri ); |
|
788 User::LeaveIfError( index.Status() ); |
|
789 for ( TInt i = 0; i < lmCount; i++ ) |
|
790 { |
|
791 index.Remove( ids[i] ); |
|
792 } |
|
793 CleanupStack::PopAndDestroy( buf ); |
|
794 |
|
795 LmServerGlobal::Complete( aMessage, KErrNone ); |
|
796 } |
|
797 |
|
798 // ----------------------------------------------------------------------------- |
|
799 // ----------------------------------------------------------------------------- |
|
800 // |
|
801 void CPosLmLocalAccessSubsession::HandleNameIndexStatusL( const RMessage2& aMessage ) |
|
802 { |
|
803 AssertIndexLoadedL(); |
|
804 CPosLmNameIndex& index = Server()->IndexManager().Index( *iDbUri ); |
|
805 TInt status = index.Status(); |
|
806 if ( status < 0 ) |
|
807 LmServerGlobal::Complete( aMessage, status ); |
|
808 else |
|
809 LmServerGlobal::Complete( aMessage, index.Count() ); |
|
810 } |
|
811 |
|
812 // ----------------------------------------------------------------------------- |
|
813 // ----------------------------------------------------------------------------- |
|
814 // |
|
815 void CPosLmLocalAccessSubsession::HandleUseNameIndexL( |
|
816 const RMessage2& aMessage ) |
|
817 { |
|
818 switch ( aMessage.Function() ) |
|
819 { |
|
820 case EPosLmServerOpenNameIndex: |
|
821 { |
|
822 if ( iUsingNameIndex ) |
|
823 { |
|
824 PanicClient( aMessage, EPosClientHasAlreadyRegistered ); |
|
825 return; |
|
826 } |
|
827 // Register new user of lm index |
|
828 Server()->IndexManager().AddIndexUserL( *iDbUri ); |
|
829 iUsingNameIndex = ETrue; |
|
830 break; |
|
831 } |
|
832 case EPosLmServerCloseNameIndex: |
|
833 { |
|
834 if ( !iUsingNameIndex ) |
|
835 { |
|
836 PanicClient( aMessage, EPosClientHasNotRegistered ); |
|
837 return; |
|
838 } |
|
839 Server()->IndexManager().RemoveIndexUser( *iDbUri ); |
|
840 iUsingNameIndex = EFalse; |
|
841 break; |
|
842 } |
|
843 default: |
|
844 break; |
|
845 } |
|
846 LmServerGlobal::Complete( aMessage, KErrNone ); |
|
847 } |
|
848 |
|
849 // ----------------------------------------------------------------------------- |
|
850 // ----------------------------------------------------------------------------- |
|
851 // |
|
852 void CPosLmLocalAccessSubsession::AssertIndexLoadedL() |
|
853 { |
|
854 if ( Server()->IndexManager().Find( *iDbUri ) < 0 ) |
|
855 { |
|
856 User::Leave( KErrNotFound ); |
|
857 } |
|
858 } |