cbs/CbsServer/ServerSrc/CCbsDbImp.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Mar 2010 09:40:14 +0200
changeset 12 ae8abd0db65c
parent 0 ff3b6d0fd310
child 50 2313cb430f28
permissions -rw-r--r--
Revision: 201007 Kit: 201011

/*
* Copyright (c) 2003 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:  This contains basis for the implementation of the database.
*    
*                Constructs instances of database subclasses CCbsDbImpSettings,
*                CCbsDbImpTopicCollection, CCbsDbTopicList and CCbsDbTopicMessages.
*                On initialization determines whether datafiles already exist.
*                If all of them are present and valid, no special action is taken.
*
*                If some or all datafiles are missing or corrupt, all datafiles
*                are deleted and new files created.
*                Factory default settings, if available, are then loaded from
*                Shared Data and stored in server datafiles. This is done by
*                database subinstances.
*
*/


//  INCLUDE FILES

#include <barsc.h>
#include <e32svr.h>
#include <bautils.h>

#include <CbsServer.rsg>

#include "CbsUtils.h"
#include "CbsServerPanic.h"
#include "CCbsDbImp.H"
#include "CbsDbConstants.h"
#include "CCbsDbImpSettings.H"
#include "CCbsDbImpTopicMessages.h"
#include "CCbsDbImpTopicList.h"
#include "CCbsDbImpTopicCollection.h"
#include "CCbsBackupMonitor.h"
#include "CCbsDiskSpaceMonitor.h"

#include "CbsLogger.h"

// Data file names
_LIT( KCbsTopicsAndMsgsFileName, "cbtopicsmsgs.dat" );
_LIT( KCbsUnsavedMsgsFileName, "cbunsaved.dat" );

// ================= MEMBER FUNCTIONS =======================

// -----------------------------------------------------------------------------
// CCbsDbImp::CCbsDbImp
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CCbsDbImp::CCbsDbImp()
    {
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CCbsDbImp::ConstructL()
    {
    User::LeaveIfError( iFs.Connect() );

    // Create the disk space monitor    
    iDiskSpaceMonitor = CCbsDiskSpaceMonitor::NewL( *this );

    TInt errorCode( KErrNone );
    
#ifdef __SECURE_BACKUP__
    // Use PubSub for monitoring
    iBackupMonitor = CCbsBackupMonitor::NewL( *this );
#else
    // Create a backup observer wrapper. If an error is returned,
    // ignore it and leave iBackupWrapper to NULL.
    TRAP( errorCode, ( iBackupWrapper = CBaBackupSessionWrapper::NewL() ) );
#endif        

    // Try to create the database components. If we couldn't because
    // the disk is almost full, that's alright. We'll try again
    // later.
    TRAP( errorCode, CreateComponentsL() );
    if ( errorCode == KErrDiskFull )
        {
        // Install an observer for the critical level
        WaitForCriticalLevel();
        }
    else
        {
        User::LeaveIfError( errorCode );
        }
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CCbsDbImp* CCbsDbImp::NewL()
    {
    CCbsDbImp* self = new ( ELeave ) CCbsDbImp;
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

// Destructor
CCbsDbImp::~CCbsDbImp()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsDbImp::~CCbsDbImp()");
    if ( iDiskSpaceMonitor )
        {
        delete iDiskSpaceMonitor;
        }    
    
    DeleteComponents();

    iFs.Close();
    CBSLOGSTRING("CBSSERVER: <<< CCbsDbImp::~CCbsDbImp()");
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::TopicListL
// Returns a reference to the current active topic list. 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CCbsDbImpTopicList& CCbsDbImp::TopicListL()
    {
    // Check if we have initialized the database succesfully
    if ( !iTopicList )
        {
        User::Leave( KErrDiskFull );
        }

    return *iTopicList;    
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::TopicMessagesL
// Returns a reference to the current topic messages DB object. 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CCbsDbImpTopicMessages& CCbsDbImp::TopicMessagesL()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsDbImp::TopicMessagesL()");
    
    // Check if we have initialized the database succesfully
    if ( !iTopicMessages )
        {
        CBSLOGSTRING("CBSSERVER: CCbsDbImp::TopicMessagesL(): No iTopicMessages instance, leaving with KErrDiskFull...");
        User::Leave( KErrDiskFull );
        }

    CBSLOGSTRING("CBSSERVER: <<< CCbsDbImp::TopicMessagesL(), returning *iTopicMessages.");
    return *iTopicMessages;
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::SettingsL
// Returns a reference to the settings DB object.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CCbsDbImpSettings& CCbsDbImp::SettingsL()
    {
    // Check if we have initialized the database succesfully
    if ( !iSettings )
        {
        User::Leave( KErrDiskFull );
        }

    return *iSettings;
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::TopicCollectionL
// Returns a reference to the topic collection.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CCbsDbImpTopicCollection& CCbsDbImp::TopicCollectionL()
    {
    // Check if we have initialized the database succesfully
    if ( !iTopicCollection )
        {
        User::Leave( KErrDiskFull );
        }

    return *iTopicCollection;
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::BackupWrapperL
// Returns a reference to the backup wrapper. 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
CBaBackupSessionWrapper& CCbsDbImp::BackupWrapperL()
    {
    if ( !iBackupWrapper )
        {
        User::Leave( KErrGeneral );
        }

    return *iBackupWrapper;
    }

// ---------------------------------------------------------
// IsInitialized()    
//
// ---------------------------------------------------------
TBool CCbsDbImp::IsInitialized() const
    {
    return iSettings != NULL;
    }

// -----------------------------------------------------------------------------
// CCbsDbImp::CreateComponentsL
// Creates topic list, settings topic messages and topic
// collection instances and loads factory settings if necessary. 
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CCbsDbImp::CreateComponentsL()
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsDbImp::CreateComponentsL()");
    
    // Return if we have already been initialized
    if ( IsInitialized() )
        {
        return;
        }    
    
    TBuf<16> topicsFile( KCbsTopicsAndMsgsFileName );
    TBuf<16> messagesFile( KCbsUnsavedMsgsFileName );  
    
    // Delete the old file for unsaved messages 
    CbsUtils::DeleteFileL( iFs, messagesFile );
    CBSLOGSTRING("CBSSERVER: CCbsDbImp::CreateComponentsL(): messagesFile deleted.");

    // Make sure that data file paths exist.
    iFs.MkDirAll( topicsFile ); 
    iFs.MkDirAll( messagesFile ); 
    
    // Create the individual components. If creating any of the components
    // fails, this method leaves and created components are deleted.
    CCbsDbImpSettings* settings = CreateSettingsL();
    CleanupStack::PushL( settings );

    CCbsDbImpTopicList* topicList = CreateTopicListL( topicsFile, messagesFile );
    CleanupStack::PushL( topicList );

    CCbsDbImpTopicMessages* topicMessages = CreateTopicMessagesL( *topicList );
    CleanupStack::PushL( topicMessages );

    CCbsDbImpTopicCollection* topicCollection = CreateTopicCollectionL();
    CleanupStack::PushL( topicCollection );
    

#ifndef __SECURE_BACKUP__

    CBSLOGSTRING("CBSSERVER: CCbsDbImp::CreateComponentsL(): __SECURE_BACKUP__ not defined.");
    
    // Register the file to backup server
    if ( iBackupWrapper )
        {
        iBackupWrapper->RegisterFileL( *topicsFile, *topicList );
        }
#endif

    // We have succesfully created all components. Set them to member
    // variables.
    iTopicList = topicList;
    iSettings = settings;
    iTopicMessages = topicMessages;
    iTopicCollection = topicCollection;

    // Does not transfer ownership.
    iTopicList->SetTopicMessages( iTopicMessages );    

    // If we could create the database, cancel the disk space notify request
    WaitForCriticalLevelCancel();

    // The database components are preserved, but the resource reader and
    // related buffers are deleted.
    CleanupStack::Pop( 4 ); // topicMessages, settings, topicList, topicCollection
    
    CBSLOGSTRING("CBSSERVER: <<< CCbsDbImp::CreateComponentsL()");
    }

// ---------------------------------------------------------
// DeleteComponents()     
//
// ---------------------------------------------------------
void CCbsDbImp::DeleteComponents()
    {
    delete iTopicMessages;
    iTopicMessages = NULL;

    delete iTopicCollection;
    iTopicCollection = NULL;

#ifdef __SECURE_BACKUP__

#else
    // Delete owned objects and deregister files from
    // backup server.
    if ( iBackupWrapper && iSettings )
        {
        //iBackupWrapper->DeregisterFile( iSettings->FileName() );
        }
        
    if ( iBackupWrapper && iTopicList )
        {
        //iBackupWrapper->DeregisterFile( iTopicList->TopicFilename() );
        }
#endif        
        
    delete iSettings;
    iSettings = NULL;
    
    delete iTopicList;
    iTopicList = NULL;

#ifdef __SECURE_BACKUP__
    delete iBackupMonitor;
    iBackupMonitor = NULL;
#else
    delete iBackupWrapper;
    iBackupWrapper = NULL;
#endif    
    }

// ---------------------------------------------------------
// CreateSettingsL()     
//
// ---------------------------------------------------------
CCbsDbImpSettings* CCbsDbImp::CreateSettingsL()
    {
    CCbsDbImpSettings* settings = NULL;
    TRAPD( err, ( settings = CCbsDbImpSettings::NewL( *this ) ) );
    User::LeaveIfError( err );
    return settings;
    }

// ---------------------------------------------------------
// CreateTopicListL()     
//
// ---------------------------------------------------------
CCbsDbImpTopicList* CCbsDbImp::CreateTopicListL( 
    const TDesC& aTopicsFile,
    const TDesC& aMessagesFile )
    {
    // Try to create the topic list.
    CCbsDbImpTopicList* topicList = NULL;
    TRAPD( err, ( topicList = CCbsDbImpTopicList::NewL(
        iFs, aTopicsFile, aMessagesFile, *this ) ) );

    // Handle data file corruption here.
    switch ( err )
        {
        case KErrNone:
            break;

        case KErrCorrupt:
        case KErrEof:
            // The data file was corrupt. Delete it and try again.
            CbsUtils::DeleteFileL( iFs, aTopicsFile );
            CbsUtils::DeleteFileL( iFs, aMessagesFile );
            topicList = CCbsDbImpTopicList::NewL(
                iFs, aTopicsFile, aMessagesFile, *this );
            break;

        default:
            User::Leave( err );
            break;
        }

    return topicList;
    }

// ---------------------------------------------------------
// CreateTopicMessagesL()     
//
// ---------------------------------------------------------
CCbsDbImpTopicMessages* CCbsDbImp::CreateTopicMessagesL( 
    CCbsDbImpTopicList& aTopicList )
    {
    // This cannot leave because of data file corruption.
    return CCbsDbImpTopicMessages::NewL( aTopicList, iFs );
    }


// ---------------------------------------------------------
// CreateTopicCollectionL()     
//
// ---------------------------------------------------------
CCbsDbImpTopicCollection* CCbsDbImp::CreateTopicCollectionL()
    {
    // This does not create a data file.
    return CCbsDbImpTopicCollection::NewL();
    }

// ---------------------------------------------------------
// WaitForCriticalLevelL()     
//
// ---------------------------------------------------------
void CCbsDbImp::WaitForCriticalLevel()
    {
    // We are running low on disk space. Ask for a notification
    // when there is space again.
    iDiskSpaceMonitor->IssueRequest();  
    }


// ---------------------------------------------------------
// WaitForCriticalLevelCancel()     
//
// ---------------------------------------------------------
void CCbsDbImp::WaitForCriticalLevelCancel()
    {
    // Cancel the notification for critical level    
    iDiskSpaceMonitor->Cancel();    
    }

// ---------------------------------------------------------
// ChangeFileLocksL()
// 
// Releases all files for backup/restore, or takes the
// files into use again.
// ---------------------------------------------------------
    
void CCbsDbImp::ChangeFileLocksL( const TCbsBackupRequest& aRequest )
    {
    CBSLOGSTRING("CBSSERVER: >>> CCbsDbImp::ChangeFileLocksL()");
    
    // Check/change the topiclist/topics/saved messages file
    iTopicList->ChangeFileLockL( aRequest );
    
    CBSLOGSTRING("CBSSERVER: <<< CCbsDbImp::ChangeFileLocksL()");
    }

// ================= OTHER EXPORTED FUNCTIONS ==============

//  End of File