First public contribution.
1 // Copyright (c) 2004-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
18 #include "srvparams.h"
21 using namespace NCentralRepositoryConstants;
23 RRepositorySession* CClientRepository::Session()
25 return static_cast<RRepositorySession*>(Dll::Tls());
28 CClientRepository* CClientRepository::NewLC(TUid aRepositoryUid)
30 CClientRepository* rep = new(ELeave) CClientRepository();
31 CleanupStack::PushL(rep);
32 rep->ConstructL(aRepositoryUid);
36 void CClientRepository::ConstructL(TUid aRepositoryUid)
38 RRepositorySession* session = Session();
42 session = new (ELeave) RRepositorySession();
43 CleanupStack::PushL(session);
44 User::LeaveIfError(Dll::SetTls(session));
45 CleanupStack::Pop(session);
46 User::LeaveIfError(session->Connect());
50 session->IncrementSubSessionCounter();
53 iSubSession = new (ELeave) RRepositorySubSession();
54 User::LeaveIfError(iSubSession->Open(session, EInitialise, TIpcArgs(aRepositoryUid.iUid)));
57 CClientRepository::CClientRepository()
61 CClientRepository::~CClientRepository()
68 RRepositorySession* session = Session();
69 if(session && session->DecrementSubSessionCounter() == 0)
71 //The last subSesssion is closed. Time to close the session.
79 TInt CClientRepository::Create(TUint32 aId, TInt aVal)
81 return iSubSession->SendReceive(ECreateInt, TIpcArgs(aId, aVal));
84 TInt CClientRepository::Create(TUint32 aId, const TReal& aVal)
87 return iSubSession->SendReceive(ECreateReal, TIpcArgs(aId, &p));
90 TInt CClientRepository::Create(TUint32 aId, const TDesC8& aVal)
92 return iSubSession->SendReceive(ECreateString, TIpcArgs(aId, &aVal));
95 TInt CClientRepository::Create(TUint32 aId, const TDesC16& aVal)
97 TPtrC8 ptr8((const TUint8*)aVal.Ptr(), aVal.Size());
98 return iSubSession->SendReceive(ECreateString, TIpcArgs(aId, &ptr8));
101 TInt CClientRepository::Delete(TUint32 aId)
103 return iSubSession->SendReceive(EDelete, TIpcArgs(aId));
106 TInt CClientRepository::Delete(TUint32 aPartialKey, TUint32 aMask, TUint32 &aErrorKey)
108 aErrorKey = KUnspecifiedKey; // set in case not filled by server
109 TPckg<TUint32> p(aErrorKey);
110 return iSubSession->SendReceive(EDeleteRange, TIpcArgs(aPartialKey, aMask, &p));
113 TInt CClientRepository::Get(TUint32 aId, TInt& aVal)
116 return iSubSession->SendReceive(EGetInt, TIpcArgs(aId, &p));
119 TInt CClientRepository::Set(TUint32 aId, TInt aVal)
121 return iSubSession->SendReceive(ESetInt, TIpcArgs(aId, aVal));
124 TInt CClientRepository::Get(TUint32 aId, TReal& aVal)
126 TPckg<TReal> p(aVal);
127 return iSubSession->SendReceive(EGetReal, TIpcArgs(aId, &p));
130 TInt CClientRepository::Set(TUint32 aId, const TReal& aVal)
132 TPckg<TReal> p(aVal);
133 return iSubSession->SendReceive(ESetReal, TIpcArgs(aId, &p));
136 TInt CClientRepository::Get(TUint32 aId, TDes8& aVal)
138 TPckg<TInt> p(aVal.MaxLength());
139 return iSubSession->SendReceive(EGetString, TIpcArgs(aId, &aVal, &p));
142 TInt CClientRepository::Get(TUint32 aId, TDes8& aVal, TInt& aActualLen)
144 aActualLen = aVal.MaxLength();
145 TPckg<TInt> p(aActualLen);
146 return iSubSession->SendReceive(EGetString, TIpcArgs(aId, &aVal, &p));
149 TInt CClientRepository::Set(TUint32 aId, const TDesC8& aVal)
151 return iSubSession->SendReceive(ESetString, TIpcArgs(aId, &aVal));
154 TInt CClientRepository::Get(TUint32 aId, TDes& aVal)
156 TPtr8 ptr8((TUint8*)aVal.Ptr(), 0, aVal.MaxSize());
158 TPckg<TInt> p(ptr8.MaxLength());
160 TInt r = iSubSession->SendReceive(EGetString, TIpcArgs(aId, &ptr8, &p));
162 if(r==KErrNone || r==KErrOverflow)
164 TInt len = ptr8.Length();
165 // note the following handles the case where client is getting an odd-length 8-bit
166 // descriptor into 16-bit aVal. Round up length and ensure the extra byte is zero.
169 ptr8.SetLength(len+1); // set the length before trying to write the value
172 aVal.SetLength((len + 1)/2);
178 TInt CClientRepository::Get(TUint32 aId, TDes& aVal, TInt& aActualLen)
180 TPtr8 ptr8((TUint8*)aVal.Ptr(), 0, aVal.MaxSize());
182 aActualLen = ptr8.MaxLength();
183 TPckg<TInt> p(aActualLen);
185 TInt r = iSubSession->SendReceive(EGetString, TIpcArgs(aId, &ptr8, &p));
187 if(r==KErrNone || r==KErrOverflow)
189 TInt len = ptr8.Length();
190 // note the following handles the case where client is getting an odd-length 8-bit
191 // descriptor into 16-bit aVal. Round up length and ensure the extra byte is zero.
194 ptr8.SetLength(len+1); // set the length before trying to write the value
197 aVal.SetLength((len + 1)/2);
198 aActualLen = ((aActualLen + 1)/2);
204 TInt CClientRepository::Set(TUint32 aId, const TDesC& aVal)
206 TPtrC8 ptr8((const TUint8*)aVal.Ptr(), aVal.Size());
207 return iSubSession->SendReceive(ESetString, TIpcArgs(aId, &ptr8));
210 TInt CClientRepository::GetMeta(TUint32 aId, TUint32& aMeta)
212 TPckg<TUint32> p(aMeta);
213 return iSubSession->SendReceive(EGetMeta, TIpcArgs(aId, &p));
216 TInt CClientRepository::Move(TUint32 aSourcePartialId, TUint32 aTargetPartialId,
217 TUint32 aIdMask, TUint32 &aErrorId)
219 aErrorId = KUnspecifiedKey; // set in case not filled by server
220 TPckg<TUint32> p(aErrorId);
221 TKeyFilter srcKeyIdentifier = {aSourcePartialId, aIdMask};
222 TKeyFilter tgtKeyIdentifier = {aTargetPartialId, aIdMask};
223 TPckg<TKeyFilter> pSrc(srcKeyIdentifier);
224 TPckg<TKeyFilter> pTrg(tgtKeyIdentifier);
226 TInt r = iSubSession->SendReceive(EMove, TIpcArgs(&pSrc, &pTrg, &p));
231 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
232 //operations valid in transactions.
233 TInt CClientRepository::FindL(TUint32 aPartialId, TUint32 aIdMask,
234 RArray<TUint32>& aFoundIds)
236 CleanupFailTransactionPushL();
239 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
240 TUint32* start = uids.Begin();
241 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
242 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
243 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
245 TInt r = iSubSession->SendReceive(EFind, TIpcArgs(&pIdentifier, 0, &ptr));
249 r = GetFindResult(uids, aFoundIds);
251 User::LeaveNoMemory();
259 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
260 //operations valid in transactions.
261 TInt CClientRepository::FindEqL(TUint32 aPartialId, TUint32 aIdMask, TInt aVal,
262 RArray<TUint32>& aFoundIds)
264 CleanupFailTransactionPushL();
267 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
268 TUint32* start = uids.Begin();
269 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
270 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
271 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
273 TInt r = iSubSession->SendReceive(EFindEqInt, TIpcArgs(&pIdentifier, aVal, &ptr));
277 r = GetFindResult(uids, aFoundIds);
279 User::LeaveNoMemory();
287 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
288 //operations valid in transactions.
289 TInt CClientRepository::FindEqL(TUint32 aPartialId, TUint32 aIdMask,
290 const TReal& aVal, RArray<TUint32>& aFoundIds)
292 CleanupFailTransactionPushL();
295 TPckg<TReal> pVal(aVal);
296 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
297 TUint32* start = uids.Begin();
298 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
299 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
300 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
302 TInt r = iSubSession->SendReceive(EFindEqReal, TIpcArgs(&pIdentifier, &pVal, &ptr));
306 r = GetFindResult(uids, aFoundIds);
308 User::LeaveNoMemory();
316 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
317 //operations valid in transactions.
318 TInt CClientRepository::FindEqL(TUint32 aPartialId, TUint32 aIdMask,
319 const TDesC8& aVal, RArray<TUint32>& aFoundIds)
321 CleanupFailTransactionPushL();
324 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
325 TUint32* start = uids.Begin();
326 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
327 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
328 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
330 TInt r = iSubSession->SendReceive(EFindEqString, TIpcArgs(&pIdentifier, &aVal, &ptr));
334 r = GetFindResult(uids, aFoundIds);
336 User::LeaveNoMemory();
344 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
345 //operations valid in transactions.
346 TInt CClientRepository::FindEqL(TUint32 aPartialId, TUint32 aIdMask,
347 const TDesC& aVal, RArray<TUint32>& aFoundIds)
349 CleanupFailTransactionPushL();
352 TPtrC8 pVal((const TUint8*)aVal.Ptr(), aVal.Length()*2);
353 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
354 TUint32* start = uids.Begin();
355 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
356 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
357 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
359 TInt r = iSubSession->SendReceive(EFindEqString, TIpcArgs(&pIdentifier, &pVal, &ptr));
363 r = GetFindResult(uids, aFoundIds);
365 User::LeaveNoMemory();
373 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
374 //operations valid in transactions.
375 TInt CClientRepository::FindNeqL(TUint32 aPartialId, TUint32 aIdMask,
376 TInt aVal, RArray<TUint32>& aFoundIds)
378 CleanupFailTransactionPushL();
381 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
382 TUint32* start = uids.Begin();
383 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
384 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
385 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
387 TInt r = iSubSession->SendReceive(EFindNeqInt, TIpcArgs(&pIdentifier, aVal, &ptr));
391 r = GetFindResult(uids, aFoundIds);
393 User::LeaveNoMemory();
401 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
402 //operations valid in transactions.
403 TInt CClientRepository::FindNeqL(TUint32 aPartialId, TUint32 aIdMask,
404 const TReal& aVal, RArray<TUint32>& aFoundIds)
406 CleanupFailTransactionPushL();
409 TPckg<TReal> pVal(aVal);
410 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
411 TUint32* start = uids.Begin();
412 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
413 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
414 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
416 TInt r = iSubSession->SendReceive(EFindNeqReal, TIpcArgs(&pIdentifier, &pVal, &ptr));
420 r = GetFindResult(uids, aFoundIds);
422 User::LeaveNoMemory();
430 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
431 //operations valid in transactions.
432 TInt CClientRepository::FindNeqL(TUint32 aPartialId, TUint32 aIdMask,
433 const TDesC8& aVal, RArray<TUint32>& aFoundIds)
435 CleanupFailTransactionPushL();
438 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
439 TUint32* start = uids.Begin();
440 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
441 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
442 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
444 TInt r = iSubSession->SendReceive(EFindNeqString, TIpcArgs(&pIdentifier, &aVal, &ptr));
448 r = GetFindResult(uids, aFoundIds);
450 User::LeaveNoMemory();
458 //Calls FailTransaction if it Leaves. This is the pattern for all client-side failure of
459 //operations valid in transactions.
460 TInt CClientRepository::FindNeqL(TUint32 aPartialId, TUint32 aIdMask,
461 const TDesC& aVal, RArray<TUint32>& aFoundIds)
463 CleanupFailTransactionPushL();
466 TPtrC8 pVal((const TUint8*)aVal.Ptr(), aVal.Length()*2);
467 TFixedArray<TUint32, KCentRepFindWithLenghtBufSize> uids;
468 TUint32* start = uids.Begin();
469 TPtr8 ptr(reinterpret_cast<TUint8*>(start), uids.Count() * uids.Length());
470 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
471 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
473 TInt r = iSubSession->SendReceive(EFindNeqString, TIpcArgs(&pIdentifier, &pVal, &ptr));
477 r = GetFindResult(uids, aFoundIds);
479 User::LeaveNoMemory();
487 /** Private helper function for all the Find~L functions.
488 No need to call FailTransaction since all the methods that call this method calls
489 FailTransaction prior to this method.
492 TInt CClientRepository::GetFindResult(const TFixedArray<TUint32, KCentRepFindWithLenghtBufSize>& aUids, RArray<TUint32>& aFoundIds)
494 iClientErr = KErrNone;
495 const TUint32 numFound = aUids[0];
496 const TUint32 numInitial = numFound > KCentRepFindBufSize ? KCentRepFindBufSize : numFound;
497 const TUint32 numFinal = numFound > KCentRepFindBufSize ? numFound - KCentRepFindBufSize : 0;
499 for(TUint32 i = 1; i <= numInitial; i++)
501 //initialise client error first
502 iClientErr=aFoundIds.Append(aUids[i]);
503 if (iClientErr!=KErrNone)
509 TAny* tempBuf = User::Alloc(numFinal * sizeof(TUint32));
514 TPtr8 p(static_cast<TUint8*>(tempBuf), numFinal * sizeof(TUint32));
515 TInt r = iSubSession->SendReceive(EGetFindResult, TIpcArgs(&p));
518 for(TUint32 i = 0; i < numFinal; i++)
520 iClientErr=aFoundIds.Append(static_cast<const TUint32*>(tempBuf)[i]);
521 if (iClientErr!=KErrNone)
533 TInt CClientRepository::NotifyRequest(TUint32 aId, TRequestStatus& aStatus)
535 TInt r = iSubSession->SendReceive(ENotifyRequestCheck, TIpcArgs(aId));
537 iSubSession->SendReceive(ENotifyRequest, TIpcArgs(aId), aStatus);
541 TInt CClientRepository::NotifyCancel(TUint32 aId)
543 return iSubSession->SendReceive(ENotifyCancel, TIpcArgs(aId));
546 TInt CClientRepository::NotifyCancelAll()
548 return iSubSession->SendReceive(ENotifyCancelAll);
551 TInt CClientRepository::NotifyRequest(TUint32 aPartialId, TUint32 aIdMask,
552 TRequestStatus& aStatus)
554 iSubSession->SendReceive(EGroupNotifyRequest,
555 TIpcArgs(aPartialId, aIdMask), aStatus);
559 TInt CClientRepository::NotifyCancel(TUint32 aPartialId, TUint32 aIdMask)
561 TKeyFilter keyIdentifier = {aPartialId, aIdMask};
562 TPckg<TKeyFilter> pIdentifier(keyIdentifier);
564 return iSubSession->SendReceive(EGroupNotifyCancel, TIpcArgs(&pIdentifier));
567 TInt CClientRepository::Reset()
569 return iSubSession->SendReceive(EResetAll);
572 TInt CClientRepository::Reset(TUint32 aId)
574 return iSubSession->SendReceive(EReset, TIpcArgs(aId));
577 TInt CClientRepository::StartTransaction(TTransactionMode aMode)
579 return iSubSession->SendReceive(ETransactionStart, TIpcArgs(aMode));
582 void CClientRepository::StartTransaction(TTransactionMode aMode, TRequestStatus& aStatus)
584 iSubSession->SendReceive(ETransactionStart, TIpcArgs(aMode), aStatus);
587 TInt CClientRepository::CommitTransaction(TUint32& aKeyInfo)
589 // set to KUnspecifiedKey in case failure happens before setting in server
590 aKeyInfo = KUnspecifiedKey;
591 TPckg<TUint32> p(aKeyInfo);
592 return iSubSession->SendReceive(ETransactionCommit, TIpcArgs(&p));
595 void CClientRepository::CommitTransaction(TDes8& aKeyInfo, TRequestStatus& aStatus)
597 // set to KUnspecifiedKey in case failure happens before setting in server
598 aKeyInfo.Copy(TPckg<TUint32>(KUnspecifiedKey));
599 iSubSession->SendReceive(ETransactionCommit, TIpcArgs(&aKeyInfo), aStatus);
602 void CClientRepository::CancelTransaction()
604 iSubSession->SendReceive(ETransactionCancel);
607 static void CancelTransactionCleanupOperation(TAny* aRepository)
609 static_cast<CClientRepository*>(aRepository)->CancelTransaction();
612 // So CancelTransaction is called in case of Leave. Must pop with CleanupStack::Pop() or similar
613 void CClientRepository::CleanupCancelTransactionPushL()
615 CleanupStack::PushL(TCleanupItem(CancelTransactionCleanupOperation, this));
618 void CClientRepository::FailTransaction()
620 if (iClientErr==KErrNone)
621 iSubSession->SendReceive(ETransactionFail,TIpcArgs(KErrAbort));
623 iSubSession->SendReceive(ETransactionFail,TIpcArgs(iClientErr));
624 //reset the internal client code
628 // So FailTransaction is called in case of Leave. Must pop with CleanupStack::Pop() or similar
629 static void FailTransactionCleanupOperation(TAny* aRepository)
631 static_cast<CClientRepository*>(aRepository)->FailTransaction();
634 void CClientRepository::CleanupFailTransactionPushL()
636 CleanupStack::PushL(TCleanupItem(FailTransactionCleanupOperation, this));
639 TInt CClientRepository::TransactionState()
643 TPckg<TInt> p(iValue);
645 iSubSession->SendReceive(ETransactionState, TIpcArgs(&p));
650 TInt RRepositorySubSession::Open(RRepositorySession* aSession,TInt aFunction,const TIpcArgs& aArgs)
653 return(CreateSubSession(*aSession, aFunction, aArgs));
656 void RRepositorySubSession::Close()
658 RSubSessionBase::CloseSubSession(EClose);
661 TInt RRepositorySubSession::SendReceive(TInt aFunction) const
663 return RSubSessionBase::SendReceive(aFunction);
666 TInt RRepositorySubSession::SendReceive(TInt aFunction, const TIpcArgs& aArgs) const
668 return RSubSessionBase::SendReceive(aFunction, aArgs);
671 void RRepositorySubSession::SendReceive(TInt aFunction, const TIpcArgs& aArgs, TRequestStatus& aStatus) const
673 RSubSessionBase::SendReceive(aFunction, aArgs, aStatus);
676 inline TInt RRepositorySession::IncrementSubSessionCounter()
678 return ++iSubSessionCounter;
681 RRepositorySession ::RRepositorySession()
682 :iSubSessionCounter(1)
686 inline TInt RRepositorySession::DecrementSubSessionCounter()
688 ASSERT(iSubSessionCounter > 0);
689 return --iSubSessionCounter;
692 #if defined(__CENTREP_SERVER_PERFTEST__) || defined(__CENTREP_SERVER_MEMTEST__) || defined(__CENTREP_SERVER_CACHETEST__)
693 TInt RRepositorySession::SendReceive(TInt aFunction) const
695 return RSessionBase::SendReceive(aFunction);
698 TInt RRepositorySession::SendReceive(TInt aFunction,
699 const TIpcArgs& aArgs) const
701 return RSessionBase::SendReceive(aFunction, aArgs);
704 void RRepositorySession::SendReceive(TInt aFunction, const TIpcArgs& aArgs,
705 TRequestStatus& aStatus) const
707 RSessionBase::SendReceive(aFunction, aArgs, aStatus);
711 LOCAL_C TInt StartServer();
713 TInt RRepositorySession::Connect()
715 const TVersion KVersion(KServerMajorVersion, KServerMinorVersion,
716 KServerBuildVersion);
718 TInt err = KErrGeneral;
719 // Use unlimited message slots as we can call subscribe multiple times per
721 TInt numMessageSlots = -1;
724 // Try to create a new session with the server.
725 err = CreateSession(KServerName, KVersion, numMessageSlots);
726 if((err != KErrNotFound) && (err != KErrServerTerminated))
728 // Server not running, try to start it.
732 if((err != KErrNone) && (err != KErrAlreadyExists))
733 break; // Launched server
739 // Start the server process or thread
741 LOCAL_C TInt StartServer()
743 const TUidType serverUid(KNullUid,KNullUid,KServerUid3);
745 // EPOC and EKA2 is easy, we just create a new server process. Simultaneous
746 // launching of two such processes should be detected when the second one
747 // attempts to create the server object, failing with KErrAlreadyExists.
750 TInt r=server.Create(KServerImg,KNullDesC,serverUid);
755 server.Rendezvous(stat);
756 if (stat!=KRequestPending)
757 server.Kill(0); // abort startup
759 server.Resume(); // logon OK - start the server
760 User::WaitForRequest(stat); // wait for start or death
761 // we can't use the 'exit reason' if the server panicked as this
762 // is the panic 'reason' and may be '0' which cannot be distinguished
764 r=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();