logsui/logsengine/logssymbianos/src/logsdbconnector.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 04 May 2010 12:39:37 +0300
changeset 0 4a5361db8937
child 6 41c0a814d878
permissions -rw-r--r--
Revision: 201015 Kit: 201018

/*
* Copyright (c) 2009 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:
*
*/

// INCLUDE FILES
#include "logsdbconnector.h"
#include "logsevent.h"
#include "logsengdefs.h"
#include "logsreader.h"
#include "logslogger.h"
#include "logsremove.h"
#include "logscommondata.h"
#include <logcli.h>
#include <f32file.h>
#include <centralrepository.h>
#include <LogsDomainCRKeys.h>

// CONSTANTS


// ----------------------------------------------------------------------------
// LogsDbConnector::LogsDbConnector
// ----------------------------------------------------------------------------
//
LogsDbConnector::LogsDbConnector( 
    QList<LogsEvent*>& events, bool checkAllEvents, bool resourceControl ) 
: QObject(), 
  mModelEvents( events ), 
  mCheckAllEvents( checkAllEvents ),
  mResourceControl( resourceControl ),
  mLogClient( 0 ), 
  mReader( 0 ),
  mLogsRemove( 0 ),
  mRepository( 0 ),
  mCompressionEnabled(false)
{
    LOGS_QDEBUG( "logs [ENG] <-> LogsDbConnector::LogsDbConnector()" )
    mFsSession = new RFs();
}

// ----------------------------------------------------------------------------
// LogsDbConnector::~LogsDbConnector
// ----------------------------------------------------------------------------
//
LogsDbConnector::~LogsDbConnector()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::~LogsDbConnector()" )
    
    delete mReader;
    delete mLogsRemove;
    delete mLogClient;
    if ( mFsSession ){
        mFsSession->Close();
    }
    delete mFsSession;
    
    qDeleteAll( mEvents );
    qDeleteAll( mDuplicatedEvents );
    
    delete mRepository;
    
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::~LogsDbConnector()" )
}

// ----------------------------------------------------------------------------
// LogsDbConnector::init
// ----------------------------------------------------------------------------
//
int LogsDbConnector::init()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::init()" )
    
    TRAPD( err, initL() );
    handleTemporaryError(err);
    
    LOGS_QDEBUG_2( "logs [ENG] <- LogsDbConnector::init(), err:", err )
    
    return err;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::start
// ----------------------------------------------------------------------------
//
int LogsDbConnector::start()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::start()" )

#ifdef LOGSDBCONNECTOR_SIMULATION
    
    LOGS_QDEBUG( "logs [ENG]    Simulation enabled" )
    int numEvents = 16;
    QList<int> indexes;
    for ( int i = 0; i < numEvents; i++ ){
        QString number = QString("1223456%1").arg(i);
        LogsEvent* event = new LogsEvent;
        if ( i % 3 == 0 ){
            event->setDirection(LogsEvent::DirMissed);
            number += QString("DirMissed");        
        }
        else if ( i % 2 == 0 ){
            event->setDirection(LogsEvent::DirIn);
            number += QString("DirIn");
        } else {
            event->setDirection(LogsEvent::DirOut);
            number += QString("DirOut");
        }
        event->setNumber(number);
        mEvents.append(event);
        mModelEvents.append(event);
        indexes.append(i);
    }
    emit dataAdded( indexes );
    return 0;
    
#endif
    
    if ( !mReader ){
        LOGS_QDEBUG( "logs [ENG]    Not initialized, failure" )
        return -1;
    }
    int err = mReader->start();
    handleTemporaryError(err);
    
    LOGS_QDEBUG_2( "logs [ENG] <- LogsDbConnector::start(), err:", err )
    return err;
}


// ----------------------------------------------------------------------------
// LogsDbConnector::updateDetails
// ----------------------------------------------------------------------------
//
int LogsDbConnector::updateDetails(bool clearCached)
{
    if ( !mReader ){
        LOGS_QDEBUG( "logs [ENG]    Not initialized, failure" )
        return -1;
    }
    mReader->updateDetails(clearCached);    
    readCompleted( mEvents.count() ); //to notify of model update
    return 0;    
}

// ----------------------------------------------------------------------------
// LogsDbConnector::stateChanged
// ----------------------------------------------------------------------------
//
void LogsDbConnector::initL()
{
    if ( mReader ){
        // Already initialized
        return;
    }  
    User::LeaveIfError( mFsSession->Connect() );
    mLogClient = CLogClient::NewL( *mFsSession );
    mLogsRemove = new LogsRemove( *this, mCheckAllEvents );
    
    TLogString logString;
    //Texts in LOGWRAP.RLS / LOGWRAP.RSS        
    User::LeaveIfError( mLogClient->GetString( logString, R_LOG_DIR_IN ) );
    mLogEventStrings.iInDirection = DESC_TO_QSTRING( logString );
    User::LeaveIfError( mLogClient->GetString( logString, R_LOG_DIR_OUT ) );
    mLogEventStrings.iOutDirection = DESC_TO_QSTRING( logString );
    User::LeaveIfError( mLogClient->GetString( logString, R_LOG_DIR_MISSED ) );
    mLogEventStrings.iMissedDirection = DESC_TO_QSTRING( logString );
    //"Unknown" (Logwrap.rls)
    User::LeaveIfError( mLogClient->GetString( logString, R_LOG_REMOTE_UNKNOWN ) ); 
    mLogEventStrings.iUnKnownRemote = DESC_TO_QSTRING( logString );
    //"Incoming on alternate line"
    User::LeaveIfError( mLogClient->GetString( logString, R_LOG_DIR_IN_ALT ) ); 
    mLogEventStrings.iInDirectionAlt = DESC_TO_QSTRING( logString );
    User::LeaveIfError( mLogClient->GetString( logString, R_LOG_DIR_OUT_ALT ) );
    mLogEventStrings.iOutDirectionAlt = DESC_TO_QSTRING( logString );
    User::LeaveIfError( mLogClient->GetString( logString, R_LOG_DIR_FETCHED) );
    mLogEventStrings.iFetched = DESC_TO_QSTRING( logString );
    
    mReader = new LogsReader( 
        *mFsSession, *mLogClient, mLogEventStrings, mEvents, *this, mCheckAllEvents );
    
    mRepository = CRepository::NewL( KCRUidLogs );
    
    if ( mResourceControl ){
        LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::initL(), resource control enabled" )
        LogsCommonData::getInstance().configureReadSize(
                logsReadSizeCompressEnabled, LogsEvent::DirUndefined);
        mCompressionEnabled = true;
    }
}

// ----------------------------------------------------------------------------
// LogsDbConnector::clearList
// ----------------------------------------------------------------------------
//
bool LogsDbConnector::clearList(LogsModel::ClearType cleartype)
{
    bool clearingStarted(false);
	if ( mLogsRemove ){
		clearingStarted = mLogsRemove->clearList(cleartype);
	}
	return clearingStarted;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::clearEvent
// ----------------------------------------------------------------------------
//
bool LogsDbConnector::clearEvents(const QList<int>& eventIds)
{
    bool asyncClearingStarted(false);
    if ( mLogsRemove ){
        bool async(false);
        int err = mLogsRemove->clearEvents(eventIds, async);
        asyncClearingStarted = ( !err && async );
    }    
    return asyncClearingStarted;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::markEventsSeen
// ----------------------------------------------------------------------------
//
bool LogsDbConnector::markEventsSeen(const QList<int>& eventIds)
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::markEventsSeen()" )
    
    if ( !mReader ){
        return false;
    }
    
    foreach( int currId, eventIds ){
        if ( !mEventsSeen.contains(currId) ){
            mEventsSeen.append(currId);
        }
    }

    LOGS_QDEBUG_2( "logs [ENG] -> event ids:", mEventsSeen );  
    
    int err = doMarkEventSeen();
    LOGS_QDEBUG_2( "logs [ENG] <- LogsDbConnector::markEventsSeen(), marking err:", 
                   err )
    return ( err == 0 );
}

// ----------------------------------------------------------------------------
// LogsDbConnector::clearMissedCallsCounter
// ----------------------------------------------------------------------------
//
int LogsDbConnector::clearMissedCallsCounter()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::clearMissedCallsCounter()" )
    if ( !mRepository ){
        return -1;
    }
    TInt value(0);
    int err = mRepository->Get( KLogsNewMissedCalls, value );
    if ( !err && value != 0 ){
        err = mRepository->Set( KLogsNewMissedCalls, 0 );
    }
    LOGS_QDEBUG_2( "logs [ENG] <- LogsDbConnector::clearMissedCallsCounter(), err", err )
    return err;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::readDuplicates
// ----------------------------------------------------------------------------
//
int LogsDbConnector::readDuplicates(int eventId)
{
    LOGS_QDEBUG_2( "logs [ENG] -> LogsDbConnector::readDuplicates(), id", eventId )
    if ( !mReader ){
        return -1;
    }
    qDeleteAll(mDuplicatedEvents);
    mDuplicatedEvents.clear();
    return mReader->readDuplicates(eventId);
}

// ----------------------------------------------------------------------------
// LogsDbConnector::takeDuplicates
// ----------------------------------------------------------------------------
//
QList<LogsEvent*> LogsDbConnector::takeDuplicates()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::takeDuplicates()" )
    QList<LogsEvent*> duplicates = mDuplicatedEvents;
    mDuplicatedEvents.clear();
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::takeDuplicates()" )
    return duplicates;
} 

// -----------------------------------------------------------------------------
// Do refresh only if compression has been enabled. Monitoring for database
// changes is restored and current database contents are read.
// -----------------------------------------------------------------------------
//
int LogsDbConnector::refreshData()
{
    if ( !mResourceControl ){
        return -1;
    }
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::refreshData()" )
    int err = 0;
    bool prevCompressionEnabled = mCompressionEnabled;
    mCompressionEnabled = false;
    LogsCommonData::getInstance().configureReadSize(
        logsReadSizeUndefined, LogsEvent::DirUndefined);
    if ( mReader ){
        if ( prevCompressionEnabled && !mReader->IsActive() ){
            err = mReader->start();
        }
    }
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::refreshData()" )
    return err;
}

// -----------------------------------------------------------------------------
// Compress data, only defined amount of events are kept in memory, others
// are deleted and read back to memory once refreshData is called. Also
// monitoring for database changes is disabled.
// -----------------------------------------------------------------------------
//
int LogsDbConnector::compressData()
{
    if ( !mResourceControl ){
        return -1;
    }
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::compressData()" )
    mCompressionEnabled = true;
    LogsCommonData::getInstance().configureReadSize(
        logsReadSizeCompressEnabled, LogsEvent::DirUndefined);
    if ( mReader ){
        int numEventsLeftInMemory = qMin(mEvents.count(), logsReadSizeCompressEnabled );
        // Simulate disappearing of compressed events
        QList<int> removedIndexes;
        for ( int i = 0; i < mEvents.count(); i++ ){
            if ( i == 0 ){
                mModelEvents.clear();
            }
            if ( i < numEventsLeftInMemory ){
                mModelEvents.append(mEvents.at(i));
            } else {
                removedIndexes.append(mEvents.at(i)->index());
            }
        }
        emit dataRemoved(removedIndexes);
        deleteRemoved( numEventsLeftInMemory );
        mReader->stop();
    }
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::compressData()" )
    return 0;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::predictiveSearchStatus
// ----------------------------------------------------------------------------
//
int LogsDbConnector::predictiveSearchStatus()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::predictiveSearchStatus()" )
    int status(-1);   
    if ( mRepository ) {
        TInt value(0);
        status = mRepository->Get( KLogsPredictiveSearch, value );
        if ( !status ) { 
            status = value;
        }
    }    
    LOGS_QDEBUG_2( "logs [ENG] <- LogsDbConnector::predictiveSearchStatus(), status:",
            status )
    return status;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::setPredictiveSearch
// ----------------------------------------------------------------------------
//
int LogsDbConnector::setPredictiveSearch(bool enabled)
{
    int err(-1);
    int status = predictiveSearchStatus();
    //if status == 0, it means that predictive search is permanently Off
    //and we are not allowed to modify it
    if (status != 0 && mRepository) {
        int value = enabled ? 1 : 2;
        err = mRepository->Set( KLogsPredictiveSearch, value );
    }
    return err;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::handleTemporaryError
// ----------------------------------------------------------------------------
//
void LogsDbConnector::handleTemporaryError(int& error)
{
     if ( error == KErrAccessDenied ){
        LOGS_QDEBUG(
            "logs [ENG] LogsDbConnector::handleTemporaryError, DB temp unavailable" )
        // TODO: handle temporary error in some meaningful way
        error = 0;
    }
}

// ----------------------------------------------------------------------------
// LogsDbConnector::deleteRemoved
// ----------------------------------------------------------------------------
//
void LogsDbConnector::deleteRemoved(int newEventCount)
{
    // Remove events which are not anymore in db nor in model,
    // such events are always at end of list
    while ( mEvents.count() > newEventCount ){
        delete mEvents.takeLast();
    }
}

// ----------------------------------------------------------------------------
// LogsDbConnector::removeCompleted
// ----------------------------------------------------------------------------
//
void LogsDbConnector::removeCompleted()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::removeCompleted()" )
    emit clearingCompleted(0);
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::removeCompleted()" )
}

// ----------------------------------------------------------------------------
// LogsDbConnector::logsRemoveErrorOccured
// ----------------------------------------------------------------------------
//
void LogsDbConnector::logsRemoveErrorOccured(int err)
{
    LOGS_QDEBUG_2( "logs [ENG] <-> LogsDbConnector::logsRemoveErrorOccured(), err:", err )
    
    emit clearingCompleted(err);
    // TODO: error handling
    
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::logsRemoveErrorOccured()" )
}

// ----------------------------------------------------------------------------
// LogsDbConnector::readCompleted
// ----------------------------------------------------------------------------
//
void LogsDbConnector::readCompleted(int readCount)
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::readCompleted()" )
    LOGS_QDEBUG_EVENT_ARR(mEvents)
    
    // Find out updated, added and removed events
    mRemovedEventIndexes.clear();
    mUpdatedEventIndexes.clear();
    mAddedEventIndexes.clear();
    for ( int i = 0; i < mEvents.count(); i++ ){
        if ( !mEvents.at(i)->isInView() ){
            mRemovedEventIndexes.append( mEvents.at(i)->index() );
        } else if ( mEvents.at(i)->eventState() == LogsEvent::EventUpdated ) {
            mUpdatedEventIndexes.append( mEvents.at(i)->index() );
        } else if ( mEvents.at(i)->eventState() == LogsEvent::EventAdded ) {
            mAddedEventIndexes.append( mEvents.at(i)->index() );
        }
    }
    
    bool doModelDataReset( !mRemovedEventIndexes.isEmpty() ||
                           !mAddedEventIndexes.isEmpty() || 
                           !mUpdatedEventIndexes.isEmpty() );
    if ( doModelDataReset ){
        mModelEvents.clear();
        int numValidEvents = qMin(mEvents.count(), readCount);
        for ( int i = 0; i < numValidEvents; i++ ){    
            mModelEvents.append(mEvents.at(i));
        }
    }
    
    if ( !mRemovedEventIndexes.isEmpty() ){
        emit dataRemoved(mRemovedEventIndexes);
    }             
    if ( !mAddedEventIndexes.isEmpty() ){
        emit dataAdded(mAddedEventIndexes);
    }
    if ( !mUpdatedEventIndexes.isEmpty() ){
        emit dataUpdated(mUpdatedEventIndexes);
    }
    
    deleteRemoved(readCount);
    
    if ( mCompressionEnabled ){
        mReader->stop();
    }    

    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::readCompleted()" )
}

// ----------------------------------------------------------------------------
// LogsDbConnector::errorOccurred
// ----------------------------------------------------------------------------
//
void LogsDbConnector::errorOccurred(int err)
{
    LOGS_QDEBUG_2( "logs [ENG] <-> LogsDbConnector::errorOccurred(), err:", err )

    // TODO: error handling
    
    handleModifyingCompletion(err);
    
    Q_UNUSED(err)
}

// ----------------------------------------------------------------------------
// LogsDbConnector::temporaryErrorOccurred
// ----------------------------------------------------------------------------
//
void LogsDbConnector::temporaryErrorOccurred(int err)
{
    LOGS_QDEBUG_2( 
            "logs [ENG] -> LogsDbConnector::temporaryErrorOccurred(), err:", err )
    
    handleTemporaryError(err);
    
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::temporaryErrorOccurred()" )
}

// ----------------------------------------------------------------------------
// LogsDbConnector::eventModifyingCompleted
// ----------------------------------------------------------------------------
//
void LogsDbConnector::eventModifyingCompleted()
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::eventModifyingCompleted()" )
    
    if ( handleModifyingCompletion() ){
        // Possible to continue modifying
        int err = doMarkEventSeen();
        if ( err != 0 ){
            // But failed for some reason
            LOGS_QDEBUG( "logs [ENG]    Couldn't continue modifying" )
            handleModifyingCompletion(err);
        }
    }
    
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::eventModifyingCompleted()" )
}

// ----------------------------------------------------------------------------
// LogsDbConnector::duplicatesReadingCompleted
// ----------------------------------------------------------------------------
//
void LogsDbConnector::duplicatesReadingCompleted(QList<LogsEvent*> duplicates)
{
    LOGS_QDEBUG( "logs [ENG] -> LogsDbConnector::duplicatesReadingCompleted()" )
    qDeleteAll( mDuplicatedEvents );
    mDuplicatedEvents.clear();
    mDuplicatedEvents = duplicates;
    emit duplicatesRead();
    LOGS_QDEBUG( "logs [ENG] <- LogsDbConnector::duplicatesReadingCompleted()" )
}

// ----------------------------------------------------------------------------
// LogsDbConnector::doMarkEventSeen
// ----------------------------------------------------------------------------
//
int LogsDbConnector::doMarkEventSeen()
{
    int err = -1;
    if ( mEventsSeen.count() > 0 ){
        err = mReader->markEventSeen(mEventsSeen.at(0));
    }
    return err;
}

// ----------------------------------------------------------------------------
// LogsDbConnector::handleModifyingCompletion
// ----------------------------------------------------------------------------
//
bool LogsDbConnector::handleModifyingCompletion(int err)
{
    bool continueModify( false );
    if ( err || mEventsSeen.count() == 1 ){
        mEventsSeen.clear();
        emit markingCompleted(err);
    } else if ( mEventsSeen.count() > 1 ){
        // Item was modified succesfully and more to modify, remove handled
        // item from queue
        mEventsSeen.takeFirst();
        continueModify = true;
    } else {
    
    }
    return continueModify;
}