Logo Search packages:      
Sourcecode: kat version File versions  Download package

katindexermanager.cpp

/***************************************************************************
 *   Copyright (C) 2005 by Roberto Cappuccio and the Kat team              *
 *   Roberto Cappuccio : roberto.cappuccio@gmail.com                       *
 *   Praveen Kandikuppa : praveen9@gmail.com                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Steet, Fifth Floor, Boston, MA 02110-1301, USA.           *
 ***************************************************************************/

#include <qapplication.h>

#include <kdebug.h>

#include <katengine.h>
#include <katcatalog.h>
#include <kattemptable.h>
#include <knotifyclient.h>
#include <klocale.h>
#include "katutils.h"
#include <math.h>
#include "katdaemonevents.h"
#include "katscheduler.h"
#include "katindexer.h"

#include "katindexermanager.h"

class IndexerData
{
public:
    IndexerData( KatCatalog* cat, KatIndexer* indexer )
    {
        m_cat = cat;
        m_indexer = indexer;
    };

    ~IndexerData()
    {
        delete m_cat;
        m_cat = 0;

        delete m_indexer;
        m_indexer = 0;
    };

    KatCatalog* m_cat;
    KatIndexer* m_indexer;

    KatIndexerStatus m_istatus;
};

class KatIndexerManagerPrivate
{
public:
    KatIndexerManagerPrivate( KatEngine* ke, KatScheduler* scheduler )
    {
        m_ke = ke;
        m_scheduler = scheduler;

        m_indexers.setAutoDelete( true );
    };

    ~KatIndexerManagerPrivate()
    {
        m_indexers.clear();

        delete m_scheduler;
        m_scheduler = 0;
        delete m_ke;
        m_ke = 0;
    };

    KatEngine* m_ke;
    KatScheduler* m_scheduler;

    QStringList m_ignoreDirs;
    QStringList m_ignoreFiles;

    QTimer m_scheduleTimer;

    QIntDict<IndexerData> m_indexers;
};

KatIndexerManager::KatIndexerManager()
{
    m_winId = 0;
    initIndexManager();
}

void KatIndexerManager::initIndexManager()
{
    // FIXME -- This needs to be worked out better
    // Probably a class in KatEngine which sets/get preferences for
    // daemon, kcm module, kat client.
    KConfig conf( "katrc" );
    conf.setGroup( "Daemon" );

    d = new KatIndexerManagerPrivate( new KatEngine(), new KatScheduler( conf.readNumEntry( "scheduler load", 20 ),
                                                                         conf.readNumEntry( "scheduler wait next job", 120 )
                                                                       ) );
    d->m_ignoreDirs = conf.readPathEntry( "Exclude Folders" );
    d->m_ignoreFiles = conf.readPathEntry( "Exclude Files" );

    connect( &d->m_scheduleTimer, SIGNAL( timeout() ), this, SLOT( slotScheduleTimeout() ) );

    QPtrList<KatCatalog> catalogs = d->m_ke->readCatalogs();

    kdDebug() << " Created engine, scheduler and read catalogs" << endl;

    KatCatalog* cat;
    for ( cat = catalogs.first(); cat; cat = catalogs.next() )
    {
        // Create the temp table
        KatTempTable* table = d->m_ke->tempTable( cat->catalogId() );
        KatIndexer* indexer = new KatIndexer( this, d->m_ke, cat, table, d->m_scheduler );
        indexer->setIgnore( d->m_ignoreDirs, d->m_ignoreFiles );

        d->m_indexers.insert( cat->catalogId(), new IndexerData( cat, indexer ) );
    }

    // Start all indexers
    startIndexer();

    emit initialized();

}

QStringList KatIndexerManager::listOfCatalog()
{
    QStringList tmp;


    QIntDictIterator<IndexerData> it( d->m_indexers );

    while ( it.current() )
    {
        tmp.append( it.current()->m_cat->name() );
        ++it;
    }

    return tmp;
}

int KatIndexerManager::schedulerLoad() const
{
    return d->m_scheduler->load();
}

void KatIndexerManager::setSchedulerLoad( int load )
{
    d->m_scheduler->setLoad( load );
}

int KatIndexerManager::maxWait() const
{
    return d->m_scheduler->maxWait();
}

void KatIndexerManager::setMaxWait( int _wait )
{
    d->m_scheduler->setMaxWait( _wait );
}


QStringList KatIndexerManager::excludeFolderList()
{
    return d->m_ignoreDirs;
}

QStringList KatIndexerManager::excludeFilesList()
{
    return d->m_ignoreFiles;
}

void KatIndexerManager::setExcludeFolderList( QStringList lst)
{
    d->m_ignoreDirs = lst;
}

void KatIndexerManager::setExcludeFilesList( QStringList lst)
{
    d->m_ignoreFiles = lst;
}

bool KatIndexerManager::addCatalog( int catalogId )
{
    if ( d->m_indexers.find( catalogId ) )
    {
        kdDebug() << " Catalog with id " << catalogId << " is already being indexed by the daemon." << endl;
        return false;
    }
    KatCatalog* catalog = d->m_ke->readCatalog( catalogId );

    KatTempTable* table = d->m_ke->tempTable( catalog->catalogId() );
    KatIndexer* indexer = new KatIndexer( this, d->m_ke, catalog, table, d->m_scheduler );
    indexer->setIgnore( d->m_ignoreDirs, d->m_ignoreFiles );

    d->m_indexers.insert( catalog->catalogId(), new IndexerData( catalog, indexer ) );

    // Start all indexers
    startIndexer( catalog->catalogId() );

    emit catalogAdded( catalogId );

    return true;
}

bool KatIndexerManager::deleteCatalog( int catalogId )
{
    IndexerData* idata = d->m_indexers.find( catalogId );
    if ( !idata )
    {
        kdDebug() << " Catalog with id " << catalogId << " does not exist. Nothing to remove." << endl;
        return false;
    }

    // Send stop event to indexer
    QApplication::postEvent( idata->m_indexer, new StopEvent() );

    // Now delete the indexer
    d->m_indexers.remove( catalogId );

    emit catalogDeleted( catalogId );

    return true;
}

bool KatIndexerManager::updateCatalog( int catalogId )
{
    if ( deleteCatalog( catalogId ) )
        return addCatalog( catalogId );
    else
        return false;
}

void KatIndexerManager::updateCatalogs()
{
    QPtrList<KatCatalog> catalogs = d->m_ke->readCatalogs();
    catalogs.setAutoDelete( true );

    IndexerData* idata = 0;
    int catalogId = 0;
    QValueList<int> catalogIds;
    KatCatalog *cat;
    for ( cat = catalogs.first(); cat; cat = catalogs.next() )
    {
        catalogId = cat->catalogId();
        idata = d->m_indexers.find( catalogId );
        if ( !idata )
            addCatalog( catalogId );
        else if ( idata && ( idata->m_cat != cat ) )
            updateCatalog( catalogId );
        catalogIds.append( catalogId );
    }

    // Now prune catalogs which dissappeared
    QIntDictIterator<IndexerData> it( d->m_indexers );
    while ( it.current() )
    {
        if ( catalogIds.find( it.currentKey() ) == catalogIds.end() )
        {
            deleteCatalog( it.currentKey() );
            continue;
        }
        ++it;
    }

    catalogs.clear();
    catalogIds.clear();
}

KatIndexerManager::~KatIndexerManager()
{
    stopIndexer();
    qApp->processEvents();

    //sleep( 3 );
    delete d;
    d = 0;
}

void KatIndexerManager::slotScheduleTimeout()
{
    if ( !d )
        return;

    bool stopTimer = true;

    // Now prune catalogs which dissappeared
    QIntDictIterator<IndexerData> it( d->m_indexers );
    while ( it.current() )
    {
        if ( it.current()->m_istatus.m_waitTime > 0 )
        {
            it.current()->m_istatus.m_waitTime--;
            if ( it.current()->m_istatus.m_waitTime > 0 )
            {
                stopTimer = false;
                emit subStatusChanged( it.current()->m_cat->catalogId(),
                                       it.current()->m_istatus.m_subStatus,
                                       subStatusString( it.current()->m_istatus ) );
            }
        }
        ++it;
    }

    if ( stopTimer )
        d->m_scheduleTimer.stop();
}

void KatIndexerManager::reInitialize()
{
    // First stop all indexers
    stopIndexer();

    // Stop the timer
    d->m_scheduleTimer.stop();

    // delete everything - KatEngine, KatScheduler, KatCatalog, KatIndexer everything
    delete d;
    d = 0;

    initIndexManager();

}

QPtrList<KatCatalog> KatIndexerManager::catalogs() const
{
    QPtrList<KatCatalog> catalogs;

    QIntDictIterator<IndexerData> it( d->m_indexers );

    while ( it.current() )
    {
        catalogs.append( it.current()->m_cat );
        ++it;
    }

    return catalogs;
}

int KatIndexerManager::eta( const KatIndexerStatus& istatus )
{
    int eta = (int)ceil( ( ( istatus.m_nFiles - istatus.m_nFilesIndexed ) * (double)istatus.m_indexTime ) / ( (double)istatus.m_nFilesIndexed * 1000 ) );
    return ( eta < 0 ) ? 0 : eta;
}

QString KatIndexerManager::statusString( const KatIndexerStatus& istatus )
{
    if ( istatus.m_status == KatIndexer::Scan )
    {
        if ( istatus.m_nFiles > 0 )
            return  i18n("Scanning 1 file/folder", "Scanning %n files/folders", istatus.m_nFiles );
        else
            return i18n("Scanning.");
    }
    else if ( istatus.m_status == KatIndexer::Prune )
        return i18n("Pruning.");
    else if ( istatus.m_status == KatIndexer::Index )
    {
        if ( ( istatus.m_nFilesIndexed > 0 ) && ( istatus.m_indexTime > 0 ) )
            return i18n("Indexing\nEstimated time remaining: %1 (1 file/folder left).",
                        "Indexing\nEstimated time remaining: %1 (%n files/folders left).",
                        istatus.m_nFiles - istatus.m_nFilesIndexed).arg(katConvertSeconds(eta(istatus)));
        else
            return i18n("Indexing.");
    }
    else if ( istatus.m_status == KatIndexer::Process )
        return i18n("Processing events.");
    else if ( istatus.m_status == KatIndexer::Wait )
        return i18n( "Waiting for events.");
    else if ( istatus.m_status == KatIndexer::Pause )
        return i18n( "Paused." );
    else if ( istatus.m_status == KatIndexer::Stop )
        return i18n( "Stopped." );
    else
        return QString( "" );
}

QString KatIndexerManager::subStatusString( const KatIndexerStatus& istatus )
{
    if ( istatus.m_subStatus == KatIndexer::AddFiles )
        return i18n( "Adding files." );
    else if ( istatus.m_subStatus == KatIndexer::DeleteFiles )
        return i18n( "Deleting files." );
    else if ( istatus.m_subStatus == KatIndexer::MoveFiles )
        return i18n( "Moving files." );
    else if ( istatus.m_subStatus == KatIndexer::AttribFiles )
        return i18n( "Updating attribute of files." );
    else if ( istatus.m_subStatus == KatIndexer::ExtractInfo )
        return i18n( "Extracting metadata/thumbnail/fulltext of files." );
    else if ( istatus.m_subStatus == KatIndexer::RequestSchedule )
        return i18n( "Requested Schedule to resume." );
    else if ( istatus.m_subStatus == KatIndexer::ScheduleTimeout )
        return i18n("Scheduled, will resume in 1 second.", "Scheduled, will resume in %n seconds.", istatus.m_waitTime);
    else if ( istatus.m_subStatus == KatIndexer::Reset )
        return QString( "" );
    else
        return QString( "" );
}

QString KatIndexerManager::currentFileString( const KatIndexerStatus& istatus )
{
    if ( ( istatus.m_filesCount < 1 ) || istatus.m_currentFile.isEmpty() )
        return QString( "" );

    QString currentFile = istatus.m_currentFile;
    if ( istatus.m_currentFile.length() > 60 )
    {
        currentFile.truncate( 28 );
        currentFile.append( " .. " ).append( istatus.m_currentFile.latin1() + istatus.m_currentFile.length() - 28 );
    }

    if ( istatus.m_status == KatIndexer::Scan )
    {
        if ( !istatus.m_currentFile.isEmpty() )
            return i18n( "Scanning directory %1.").arg(currentFile);
        else
            return i18n( "Scanning." );
    }
    else
        return i18n("file/directory %1 and 1 other.", "file/directory %1 and %n others.", istatus.m_filesCount).arg(currentFile);
}

void KatIndexerManager::customEvent( QCustomEvent* e )
{
    IndexerData* idata;

    if ( e->type() == 9004 )
    {
        // Status event
        StatusEvent* se = ( StatusEvent* )e;
        idata = d->m_indexers.find( se->catalogId() );

        if ( idata )
        {
            idata->m_istatus.m_status = ( KatIndexer::Status )se->status();

            // Reset currentFile
            idata->m_istatus.m_currentFile = QString::null;
            idata->m_istatus.m_filesCount = -1;

            emit statusChanged( se->catalogId(), idata->m_istatus.m_status, statusString( idata->m_istatus ) );
        }
    }
    else if ( e->type() == 9005 )
    {
        // SubStatus event
        SubStatusEvent* sse = ( SubStatusEvent* )e;
        idata = d->m_indexers.find( sse->catalogId() );

        if ( idata )
        {
            idata->m_istatus.m_subStatus = ( KatIndexer::SubStatus )sse->status();
            idata->m_istatus.m_subStatusData = sse->statusData();

            // Reset currentFile
            idata->m_istatus.m_currentFile = QString::null;
            idata->m_istatus.m_filesCount = -1;

            // Reset WaitTime
            if ( idata->m_istatus.m_subStatus == KatIndexer::Reset )
                idata->m_istatus.m_waitTime = 0;

            if ( idata->m_istatus.m_subStatus == KatIndexer::ScheduleTimeout )
            {
                idata->m_istatus.m_waitTime = idata->m_istatus.m_subStatusData.asInt()/1000;

                if ( !d->m_scheduleTimer.isActive() )
                    d->m_scheduleTimer.start( 1000 );
            }

            emit subStatusChanged( sse->catalogId(), idata->m_istatus.m_subStatus, subStatusString( idata->m_istatus ) );
        }
    }
    else if ( e->type() == 9015 )
    {
        // Progress Event
        ProgressEvent* pe = ( ProgressEvent* )e;
        idata = d->m_indexers.find( pe->catalogId() );

        if ( idata )
        {
            if ( idata->m_istatus.m_status == KatIndexer::Scan )
            {
                idata->m_istatus.m_nFiles = pe->filesDone();
                emit statusChanged( pe->catalogId(), idata->m_istatus.m_status, statusString( idata->m_istatus ) );
            }
            else if ( idata->m_istatus.m_status == KatIndexer::Index )
            {
                idata->m_istatus.m_nFilesIndexed = pe->filesDone();
                idata->m_istatus.m_indexTime = pe->time();
                emit statusChanged( pe->catalogId(), idata->m_istatus.m_status, statusString( idata->m_istatus ) );

                int progress = idata->m_istatus.m_nFilesIndexed*100/idata->m_istatus.m_nFiles;

                if ( progress > 100 )
                    progress = 100;

                emit progressChanged( pe->catalogId(), progress );
            }
        }
    }
    else if ( e->type() == 9016 )
    {
        // CurrentFile Event
        CurrentFileEvent* cfe = ( CurrentFileEvent* )e;
        idata = d->m_indexers.find( cfe->catalogId() );

        if ( idata )
        {
            idata->m_istatus.m_currentFile = cfe->file();
            idata->m_istatus.m_filesCount = cfe->filesCount();
            emit currentFileChanged( cfe->catalogId(), currentFileString( idata->m_istatus ) );
        }
    }
}

KatCatalog* KatIndexerManager::catalog( const int& catalogId ) const
{
    IndexerData* idata = d->m_indexers.find( catalogId );

    if ( idata && idata->m_cat )
        return idata->m_cat;
    else
        return 0;
}

bool KatIndexerManager::progress( const int& catalogId, int& progress)
{
    IndexerData* idata = d->m_indexers.find( catalogId );

    if ( idata && idata->m_cat && idata->m_indexer && ( idata->m_istatus.m_status ==KatIndexer:: Index ) )
    {
        progress = idata->m_istatus.m_nFilesIndexed*100/idata->m_istatus.m_nFiles;

        if ( progress > 100 )
            progress = 100;

        return true;
    }
    else
        return false;
}

bool KatIndexerManager::currentFileString( const int& catalogId, QString& currentFile )
{
    IndexerData* idata = d->m_indexers.find( catalogId );

    if ( idata && idata->m_cat && idata->m_indexer )
    {
        currentFile = currentFileString( idata->m_istatus );

        return true;
    }
    else
        return false;
}

bool KatIndexerManager::status( const int& catalogId, int& status, QString& istatusString )
{
    IndexerData* idata = d->m_indexers.find( catalogId );

    if ( idata && idata->m_cat && idata->m_indexer )
    {
        status = idata->m_istatus.m_status;
        istatusString = statusString( idata->m_istatus );

        return true;
    }
    else
        return false;
}

bool KatIndexerManager::subStatus( const int& catalogId, int& subStatus, QString& isubStatusString )
{
    IndexerData* idata = d->m_indexers.find( catalogId );

    if ( idata && idata->m_cat && idata->m_indexer )
    {
        subStatus = idata->m_istatus.m_subStatus;
        isubStatusString = subStatusString( idata->m_istatus );

        return true;
    }
    else
        return false;
}

bool KatIndexerManager::catalogStatus( const int& catalogId,      // catalogId
                                       int& status,               // status
                                       QString& istatusString,    // statusString
                                       int& subStatus,            // subStatus
                                       QString& isubStatusString, // subStatusString
                                       int& progress,             // progress
                                       QString& currentFile       // currentFile
                                     )
{
    IndexerData* idata = d->m_indexers.find( catalogId );

    if ( idata && idata->m_cat && idata->m_indexer )
    {
        status = idata->m_istatus.m_status;
        istatusString = statusString( idata->m_istatus );
        subStatus = idata->m_istatus.m_subStatus;
        isubStatusString = subStatusString( idata->m_istatus );
        progress = idata->m_istatus.m_nFilesIndexed*100/idata->m_istatus.m_nFiles;

        if ( progress > 100 )
            progress = 100;
        currentFile = currentFileString( idata->m_istatus );

        return true;
    }
    else
        return false;
}

void KatIndexerManager::startIndexer( const int& catalogId )
{
    KNotifyClient::event( m_winId, "StartIndexer", i18n( "Indexer file started" ) );
    if ( !catalogId )
    {
        // Send to all indexers
        QIntDictIterator<IndexerData> it( d->m_indexers );

        while ( it.current() )
        {
            if ( it.current()->m_indexer )
            {
                if ( !it.current()->m_indexer->running() )
                    it.current()->m_indexer->start();
                else
                    QApplication::postEvent( it.current()->m_indexer, new ResumeEvent() );
            }
            ++it;
        }
    }
    else
    {
        IndexerData* idata = d->m_indexers.find( catalogId );

        if ( idata && idata->m_indexer )
        {
            if ( !idata->m_indexer->running() )
                idata->m_indexer->start();
            else
                QApplication::postEvent( idata->m_indexer, new ResumeEvent() );
        }
    }
}

void KatIndexerManager::pauseIndexer( const int& catalogId )
{
    if ( !catalogId )
    {
        // Send to all indexers
        QIntDictIterator<IndexerData> it( d->m_indexers );

        while ( it.current() )
        {
            QApplication::postEvent( it.current()->m_indexer, new PauseEvent() );
            ++it;
        }
    }
    else
    {
        IndexerData* idata = d->m_indexers.find( catalogId );

        if ( idata && idata->m_indexer )
            QApplication::postEvent( idata->m_indexer, new PauseEvent() );
    }
}

void KatIndexerManager::stopIndexer( const int& catalogId )
{
    KNotifyClient::event(m_winId , "StopIndexer", i18n( "Indexer file stopped" ));
    if ( !catalogId )
    {
        // Send to all indexers
        QIntDictIterator<IndexerData> it( d->m_indexers );

        while ( it.current() )
        {
            QApplication::postEvent( it.current()->m_indexer, new StopEvent() );
            ++it;
        }
    }
    else
    {
        IndexerData* idata = d->m_indexers.find( catalogId );

        if ( idata && idata->m_indexer )
            QApplication::postEvent( idata->m_indexer, new StopEvent() );
    }
}

KatIndexerManager* KatIndexerManager::indexerManager()
{
    return new KatIndexerManager();
}

#include "katindexermanager.moc"

Generated by  Doxygen 1.6.0   Back to index