landmarks/locationlandmarks/server/src/EPos_CPosLmLocalDbManSubsession.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 27 Apr 2010 17:05:00 +0300
branchRCL_3
changeset 10 d6e4203b7ebe
parent 0 667063e416a2
permissions -rw-r--r--
Revision: 201015 Kit: 201017

/*
* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: Subsession class for local database management operations
*
*
*/


#include <EPos_TPosLmDatabaseEvent.h>
#include <epos_cposlmdiskutilities.h>
#include <epos_poslmdatabaseutility.h>
#include <EPos_HPosLmDatabaseInfo.h>
#include <EPos_CPosLmDbRegistry.h>
#include "EPos_CPosLmLocalDbManSubsession.h"
#include "EPos_CPosLmServer.h"
#include "EPos_PosLmServerCommon.h"
#include "EPos_LmServerGlobal.h"
#include "EPos_PosLmDatabaseManager.h"
#include "EPos_LandmarksServerPanics.h"

//CONSTANTS

/*   Comment on KPosMaxUriLength:
*    KPosMaxUriLength = KDbMaxName + 9;
*    KDbMaxName is the maximum length for a DBMS name: 64 characters.
*    Length of "file://c:" is 9.
*/
const TInt KPosMaxUriLength = 73;

// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::CPosLmLocalDbManSubsession
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CPosLmLocalDbManSubsession::CPosLmLocalDbManSubsession(
    CPosLmServer* aLmServer) :
    CPosLmSubsessionBase(EPosLocalDbManProviderSubsession, aLmServer)
    {
    }

// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CPosLmLocalDbManSubsession::ConstructL()
    {
    }

// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CPosLmLocalDbManSubsession* CPosLmLocalDbManSubsession::NewLC(
    CPosLmServer* aLmServer)
    {
    CPosLmLocalDbManSubsession* self =
        new (ELeave) CPosLmLocalDbManSubsession(aLmServer);
    CleanupClosePushL(*self);
    self->ConstructL();
    return self;
    }

// Destructor
CPosLmLocalDbManSubsession::~CPosLmLocalDbManSubsession()
    {
    }

// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::ServiceL
//
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CPosLmLocalDbManSubsession::ServiceL(
    const RMessage2& aMessage)
    {
    switch (aMessage.Function())
        {
        case EPosLmServerCreateDatabase:
        case EPosLmServerDeleteDatabase:
            HandleDbManagementOperationL(aMessage);
            break;
        case EPosLmServerCopyDatabase:
            HandleDbCopyOperationL(aMessage);
            break;
        default:
            User::Leave(KErrNotSupported);
            break;
        }
    }

// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::HandleDbManagementOperationL
//
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CPosLmLocalDbManSubsession::HandleDbManagementOperationL(
    const RMessage2& aMessage)
    {
    TInt dbInfoLength = aMessage.GetDesLength(KPosLmServerDbInfoArg);
    if (dbInfoLength < 0)
        {
        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
        return;
        }

    HBufC8* buf = HBufC8::NewLC(dbInfoLength);
    TPtr8 bufPtr = buf->Des();
    if (LmServerGlobal::Read(
        aMessage, KPosLmServerDbInfoArg, bufPtr) == KErrNone)
        {
        // To remove a warning, the event must be default constructed.
        TPosLmDatabaseEvent event =
            {
            EPosLmDbDatabaseRegistered,
            {0,0,0,0,0,0,0,0}
            };

        TUint8* dbInfoPtr = const_cast<TUint8*>(buf->Ptr());
        HPosLmDatabaseInfo* dbInfo =
            reinterpret_cast<HPosLmDatabaseInfo*>(dbInfoPtr);


        // verify that dbInfo size is the same as the transferred descriptor
        if(bufPtr.Length() != dbInfo->Size())
            {
            PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
            CleanupStack::PopAndDestroy(buf);
            return;
            }

        HBufC* uri =
            PosLmDatabaseUtility::CreateDatabaseUriL(dbInfo->DatabaseUri());
        CleanupStack::PushL(uri);

        CPosLmDbRegistry* reg =
            Server()->GetRegistryL(dbInfo->DatabaseDrive(), ETrue);
        if (!reg)
            {
            User::Leave(KErrGeneral);
            }

        if (aMessage.Function() == EPosLmServerCreateDatabase)
            {
            // create on disk
            CheckDiskSizeL(*uri);
            PosLmDatabaseManager::CreateDatabaseL(*uri, EFalse);

            // register
            if (dbInfo->Settings().IsAttributeSet(
                TPosLmDatabaseSettings::EName))
                {
                reg->RegisterDatabaseL(*uri, dbInfo->Settings());
                User::LeaveIfError(reg->Compact());
                }
            }
        else
            {
            // a local db URI may not exceed KPosMaxUriLength
            if (uri->Length() > KPosMaxUriLength)
                {
                User::Leave(KErrArgument);
                }

            event.iEventType = EPosLmDbDatabaseUnregistered;

            // unregister
            reg->UnregisterDatabaseL(*uri);

            // delete from disk
            PosLmDatabaseManager::DeleteDatabaseL(*uri);
            }

        Server()->ForwardEventToAllSessionsL(event, *uri);
        CleanupStack::PopAndDestroy(uri);
        LmServerGlobal::Complete(aMessage, KErrNone);
        }

    CleanupStack::PopAndDestroy(buf);
    }


// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::HandleDbCopyOperationL
//
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CPosLmLocalDbManSubsession::HandleDbCopyOperationL(
    const RMessage2& aMessage)
    {
    TInt srcDesLength = aMessage.GetDesLength(KPosLmServerSourceUriArg);
    TInt trgDesLength = aMessage.GetDesLength(KPosLmServerTargetUriArg);
    if (srcDesLength < 0 || trgDesLength < 0)
        {
        PanicClient(aMessage, EPosUnableToReadOrWriteDataToClient);
        return;
        }

    HBufC* srcUri = HBufC::NewLC(srcDesLength);
    HBufC* trgUri = HBufC::NewLC(trgDesLength);
    TPtr srcUriPtr = srcUri->Des();
    TPtr trgUriPtr = trgUri->Des();

    if (LmServerGlobal::Read(aMessage,
                             KPosLmServerSourceUriArg,
                             srcUriPtr) == KErrNone &&

        LmServerGlobal::Read(aMessage,
                             KPosLmServerTargetUriArg,
                             trgUriPtr) == KErrNone)
        {

        HBufC* sourceUri = PosLmDatabaseUtility::CreateDatabaseUriL(*srcUri);
        CleanupStack::PushL(sourceUri);
        HBufC* targetUri = PosLmDatabaseUtility::CreateDatabaseUriL(*trgUri);
        CleanupStack::PushL(targetUri);

        CheckDiskSizeForCopyL(*sourceUri, *targetUri);

        PosLmDatabaseManager::CopyDatabaseL(*sourceUri, *targetUri);

        // To remove a warning, the event must be default constructed.
        TPosLmDatabaseEvent event =
            {
            EPosLmDbDatabaseRegistered,
            {0,0,0,0,0,0,0,0}
            };

        Server()->ForwardEventToAllSessionsL(event, *targetUri);
        CleanupStack::PopAndDestroy(2, sourceUri); // targetUri

        LmServerGlobal::Complete(aMessage, KErrNone);
        }

    CleanupStack::PopAndDestroy(2, srcUri); // trgUri
    }

// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::CheckDiskSizeL
//
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CPosLmLocalDbManSubsession::CheckDiskSizeL(
    const TDesC& aUri)
    {
    CPosLmDiskUtilities* diskUtilities = CPosLmDiskUtilities::NewL();
    CleanupStack::PushL(diskUtilities);

    diskUtilities->DiskSpaceBelowCriticalLevelL(
        diskUtilities->EstimatedDiskSizeOfEmptyDatabase(),
        (aUri)[KPosLocalDbFileProtocol().Length()]);

    CleanupStack::PopAndDestroy(diskUtilities);
    }


// -----------------------------------------------------------------------------
// CPosLmLocalDbManSubsession::CheckDiskSizeForCopyL
//
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CPosLmLocalDbManSubsession::CheckDiskSizeForCopyL(
    const TDesC& aSourceUri, const TDesC& aTargetUri)
    {
        // check size of existing database
    RDbs dbSession;
    RDbNamedDatabase db;
    CleanupClosePushL(dbSession);
    CleanupClosePushL(db);

    User::LeaveIfError(dbSession.Connect());
    TPtrC sourceFile = aSourceUri;
    PosLmDatabaseUtility::RemoveProtocolFromUriL(sourceFile);
    User::LeaveIfError(db.Open(dbSession, sourceFile, KPosLmDbSecureFormat));

    TInt err = db.UpdateStats();
    if (err == KErrLocked)
        {
        err = KErrInUse;
        }
    User::LeaveIfError(err);

    TInt size = db.Size().iSize;

    CleanupStack::PopAndDestroy(2, &dbSession);  // db

    CPosLmDiskUtilities* diskUtilities = CPosLmDiskUtilities::NewL();
    CleanupStack::PushL(diskUtilities);

    diskUtilities->DiskSpaceBelowCriticalLevelL(size,
        (aTargetUri)[KPosLocalDbFileProtocol().Length()]);

    CleanupStack::PopAndDestroy(diskUtilities);
    }

// End of File