sl@0: /* sl@0: * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Implements the UPS database handle manager. See class and function sl@0: * definitions for more information. sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: #include sl@0: #include "upscommon.h" sl@0: #include sl@0: #include "upsdbmanager.h" sl@0: sl@0: namespace UserPromptService sl@0: { sl@0: sl@0: RUpsDbHandleMaster::RUpsDbHandleMaster(RFs &aFs) sl@0: /** sl@0: Construct the handle master sl@0: sl@0: This class should be used for synchronous database operations. sl@0: sl@0: If you need to do asynchronous operations then create/use an instance of the RUpsDbHandleSlave sl@0: linked to the master. sl@0: sl@0: If your database operation fails, particularly due to OOM, then you should call Close your handle. You probably sl@0: do NOT need to explicitly re-open it - it will automatically re-open when the -> operator is used. sl@0: sl@0: Note that the -> operator may leave. sl@0: */ sl@0: : iFs(aFs), iDatabase(0), iClientListHead(0) sl@0: { sl@0: } sl@0: sl@0: RUpsDbHandleMaster::~RUpsDbHandleMaster() sl@0: /** sl@0: Destroy the handle master sl@0: */ sl@0: { sl@0: ASSERT(iClientListHead == 0); // Should be no clients!!!! sl@0: Close(); // Deletes iDatabase... sl@0: iClientListHead = 0; sl@0: // Do NOT close the iFs (it is a reference to the main server's handle). sl@0: } sl@0: sl@0: _LIT(KDatabaseFile,"?:\\private\\10283558\\database\\ups.db"); sl@0: void RUpsDbHandleMaster::OpenL() sl@0: /** sl@0: Open the database handle sl@0: sl@0: It is probably clearer to explictly call this function to open the handle before first use, but the -> operator will sl@0: auto-open it if called on a closed handle. Note that the -> operator can leave. sl@0: sl@0: If any database operation fails, particularly due to OOM, then you should Close your handle. Instead of sl@0: immediately re-opening it, it is generally safer to let it auto-reopen when the -> operator is next called. sl@0: sl@0: */ sl@0: { sl@0: BULLSEYE_OFF sl@0: if(iDatabase != 0) sl@0: { sl@0: // Close/delete the existing database handle. sl@0: Close(); sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: // Open up a new handle. sl@0: TFileName databaseFileBuf = KDatabaseFile(); sl@0: sl@0: databaseFileBuf[0] = iFs.GetSystemDriveChar(); sl@0: TParsePtrC databaseFile(databaseFileBuf); sl@0: sl@0: // Make sure the dir exists sl@0: (void)iFs.MkDirAll(databaseFile.DriveAndPath()); sl@0: // Create/Open the database sl@0: iDatabase = CDecisionDbW::NewL(databaseFile.FullName(), iFs); sl@0: } sl@0: sl@0: void RUpsDbHandleMaster::Close() sl@0: /** sl@0: Notify all client handles that the master (real) database handle is about to be closed, and then close it. sl@0: */ sl@0: { sl@0: // Notify all registered clients that we are about to delete the database handle sl@0: RUpsDbHandleSlave *p = iClientListHead; sl@0: while(p) sl@0: { sl@0: ASSERT(p->iClient != 0); sl@0: p->iClient->DbHandleAboutToBeDeleted(); sl@0: p = p->iClientListNext; sl@0: } sl@0: sl@0: // Delete database handle sl@0: delete iDatabase; sl@0: iDatabase = 0; sl@0: } sl@0: sl@0: TBool RUpsDbHandleMaster::IsOpen() const sl@0: /** sl@0: Returns true if the handle is already open. sl@0: */ sl@0: { sl@0: return iDatabase != 0; sl@0: } sl@0: sl@0: CDecisionDbW *RUpsDbHandleMaster::operator->() sl@0: /** sl@0: Returns the database handle so -> can be used on an RUpsDbHandleMaster instance to call database functions sl@0: sl@0: If the database is not already open then it calls OpenL. sl@0: sl@0: This operator CAN leave. sl@0: */ sl@0: { sl@0: if(iDatabase == 0) sl@0: { sl@0: OpenL(); sl@0: } sl@0: return iDatabase; sl@0: } sl@0: sl@0: void RUpsDbHandleMaster::Register(RUpsDbHandleSlave *aClient) sl@0: /** sl@0: Register new client with us. sl@0: */ sl@0: { sl@0: BULLSEYE_OFF sl@0: if(aClient == 0) sl@0: { sl@0: return; sl@0: } sl@0: BULLSEYE_RESTORE sl@0: sl@0: aClient->iClientListNext = iClientListHead; sl@0: iClientListHead = aClient; sl@0: } sl@0: sl@0: void RUpsDbHandleMaster::UnRegister(RUpsDbHandleSlave *aClient) sl@0: /** sl@0: UnRegister client with us. sl@0: */ sl@0: { sl@0: RUpsDbHandleSlave **pp = &iClientListHead; sl@0: BULLSEYE_OFF sl@0: while(*pp) sl@0: { sl@0: BULLSEYE_RESTORE sl@0: if(*pp == aClient) sl@0: { sl@0: // Found ptr to client, so remove it. sl@0: *pp = (*pp)->iClientListNext; sl@0: aClient->iClientListNext = 0; sl@0: break; sl@0: } sl@0: pp = &(*pp)->iClientListNext; sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: RUpsDbHandleSlave::RUpsDbHandleSlave(RUpsDbHandleMaster & aMaster, MDbHandleClient * aClient) sl@0: /** sl@0: Initialise new client and register it with the RUpsDbHandleMaster sl@0: sl@0: This class is intended for use when asynchronous database operations are being performed. These may then be failed sl@0: due to another database operation failing, BUT the asycnhronous operation classes (eg. a db view) needs deleting sl@0: before the actual database handle is deleted/re-created. sl@0: */ sl@0: : iInUse(EFalse), iMaster(aMaster), iClient(aClient), iClientListNext(0) sl@0: { sl@0: ASSERT(aClient != 0); sl@0: //RDebug::Printf("RUpsDbHandleSlave(%x, %x) - %x\n", &aMaster, aClient, this); sl@0: } sl@0: sl@0: RUpsDbHandleSlave::~RUpsDbHandleSlave() sl@0: { sl@0: //RDebug::Printf("~RUpsDbHandleSlave() master %x client %x - %x\n", &iMaster, iClient, this); sl@0: Close(); sl@0: } sl@0: sl@0: CDecisionDbW *RUpsDbHandleSlave::operator->() sl@0: /** sl@0: Returns the database handle so -> can be used on an RUpsDbHandleMaster instance to call database functions sl@0: sl@0: If the database is not already open, then the master will open it. sl@0: sl@0: This operator CAN leave. sl@0: */ sl@0: { sl@0: if(!iInUse) sl@0: { sl@0: iMaster.Register(this); sl@0: iInUse = ETrue; sl@0: } sl@0: return iMaster.operator->(); sl@0: } sl@0: sl@0: void RUpsDbHandleSlave::SetCallback(MDbHandleClient *aClient) sl@0: /** sl@0: Change what callback should be run if the master handle is closed. sl@0: Do NOT set it to 0. sl@0: */ sl@0: { sl@0: ASSERT(aClient != 0); sl@0: //RDebug::Printf("RUpsDbHandleSlave::SetCallback client %x - %x\n", aClient, this); sl@0: iClient = aClient; sl@0: } sl@0: sl@0: void RUpsDbHandleSlave::Close() sl@0: /** sl@0: Close this slave handle. This does NOT close the master, it just means we de-register with the sl@0: master to we are no longer notified if the master is closed. sl@0: It will automatically re-register if the -> operator is subsequently used. sl@0: */ sl@0: { sl@0: if(iInUse) sl@0: { sl@0: iMaster.UnRegister(this); sl@0: iInUse = 0; sl@0: } sl@0: } sl@0: sl@0: void RUpsDbHandleSlave::CloseMaster() sl@0: /** sl@0: Notify all client handles that the master (real) database handle is about to be closed, and then close it. sl@0: sl@0: Typically used after a database error (particularly OOM) in an attempt to recover. Usually the database is not sl@0: explicitly re-opened, instead the re-open is defered until the next use of the -> operator on either tha master sl@0: or a client handle. sl@0: */ sl@0: { sl@0: Close(); sl@0: iMaster.Close(); sl@0: } sl@0: sl@0: sl@0: } // End of UserPromptService namespace sl@0: sl@0: // End of file