• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

NepomukDaemons

repository.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
00004  *
00005  * This file is part of the Nepomuk KDE project.
00006  * Copyright (C) 2006-2008 Sebastian Trueg <trueg@kde.org>
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  * See the file "COPYING" for the exact licensing terms.
00013  */
00014 
00015 #include "repository.h"
00016 #include "nepomukstorage-config.h"
00017 #include "modelcopyjob.h"
00018 
00019 #ifdef HAVE_CLUCENE
00020 #include "cluceneanalyzer.h"
00021 #endif
00022 
00023 #include <Soprano/Backend>
00024 #include <Soprano/Global>
00025 #include <Soprano/Version>
00026 #include <Soprano/StorageModel>
00027 #include <Soprano/Error/Error>
00028 #include <Soprano/Vocabulary/Xesam>
00029 
00030 #ifdef HAVE_SOPRANO_INDEX
00031 #include <Soprano/Index/IndexFilterModel>
00032 #include <Soprano/Index/CLuceneIndex>
00033 #endif
00034 
00035 #include <KStandardDirs>
00036 #include <KDebug>
00037 #include <KConfigGroup>
00038 #include <KSharedConfig>
00039 #include <KLocale>
00040 
00041 
00042 namespace {
00043     QString createStoragePath( const QString& repositoryId )
00044     {
00045         return KStandardDirs::locateLocal( "data", "nepomuk/repository/" + repositoryId + "/" );
00046     }
00047 }
00048 
00049 
00050 Nepomuk::Repository::Repository( const QString& name )
00051     : m_name( name ),
00052       m_state( CLOSED ),
00053       m_model( 0 ),
00054       m_analyzer( 0 ),
00055       m_index( 0 ),
00056       m_indexModel( 0 )
00057 {
00058 }
00059 
00060 
00061 Nepomuk::Repository::~Repository()
00062 {
00063     close();
00064 }
00065 
00066 
00067 void Nepomuk::Repository::close()
00068 {
00069     if ( m_state == OPEN ) {
00070 #ifdef HAVE_SOPRANO_INDEX
00071         delete m_indexModel;
00072         delete m_index;
00073         m_indexModel = 0;
00074         m_index = 0;
00075 #ifdef HAVE_CLUCENE
00076         delete m_analyzer;
00077         m_analyzer = 0;
00078 #endif
00079 #endif
00080         delete m_model;
00081         m_model = 0;
00082 
00083         m_state = CLOSED;
00084     }
00085 }
00086 
00087 
00088 void Nepomuk::Repository::open()
00089 {
00090     Q_ASSERT( m_state == CLOSED );
00091 
00092     m_state = OPENING;
00093 
00094     // get used backend
00095     // =================================
00096     const Soprano::Backend* backend = activeSopranoBackend();
00097     if ( !backend ) {
00098         m_state = CLOSED;
00099         emit opened( this, false );
00100         return;
00101     }
00102 
00103     // read config
00104     // =================================
00105     KConfigGroup repoConfig = KSharedConfig::openConfig( "nepomukserverrc" )->group( name() + " Settings" );
00106     QString oldBackendName = repoConfig.readEntry( "Used Soprano Backend", backend->pluginName() );
00107     QString oldBasePath = repoConfig.readPathEntry( "Storage Dir", QString() ); // backward comp: empty string means old storage path
00108 
00109 
00110     // If possible we want to keep the old storage path. exception: oldStoragePath is empty. In that case we stay backwards
00111     // compatible and convert the data to the new default location createStoragePath( name ) + "data/" + backend->pluginName()
00112     //
00113     // If we have a proper oldStoragePath and a different backend we use the oldStoragePath as basePath
00114     // newDataPath = oldStoragePath + "data/" + backend->pluginName()
00115     // oldDataPath = oldStoragePath + "data/" + oldBackendName
00116 
00117 
00118     // create storage paths
00119     // =================================
00120     m_basePath = oldBasePath.isEmpty() ? createStoragePath( name() ) : oldBasePath;
00121     QString indexPath = m_basePath + "index";
00122     QString storagePath = m_basePath + "data/" + backend->pluginName();
00123 
00124     KStandardDirs::makeDir( indexPath );
00125     KStandardDirs::makeDir( storagePath );
00126 
00127     kDebug(300002) << "opening repository '" << name() << "' at '" << m_basePath << "'";
00128 
00129 
00130     // open storage
00131     // =================================
00132     m_model = backend->createModel( QList<Soprano::BackendSetting>() << Soprano::BackendSetting( Soprano::BackendOptionStorageDir, storagePath ) );
00133     if ( !m_model ) {
00134         kDebug(300002) << "Unable to create model for repository" << name();
00135         m_state = CLOSED;
00136         emit opened( this, false );
00137         return;
00138     }
00139 
00140     kDebug(300002) << "Successfully created new model for repository" << name();
00141 
00142 #if defined(HAVE_SOPRANO_INDEX) && defined(HAVE_CLUCENE)
00143     m_analyzer = new CLuceneAnalyzer();
00144     m_index = new Soprano::Index::CLuceneIndex( m_analyzer );
00145 
00146     if ( m_index->open( indexPath, true ) ) {
00147         kDebug(300002) << "Successfully created new index for repository" << name();
00148         m_indexModel = new Soprano::Index::IndexFilterModel( m_index, m_model );
00149 
00150         // FIXME: find a good value here
00151         m_indexModel->setTransactionCacheSize( 100 );
00152 
00153 #if SOPRANO_IS_VERSION(2,0,99)
00154         // no need for the whole content in the store, we only need it for searching
00155         // (compare the strigi backend)
00156         m_indexModel->addIndexOnlyPredicate( Soprano::Vocabulary::Xesam::asText() );
00157 #endif
00158 
00159         setParentModel( m_indexModel );
00160     }
00161     else {
00162         kDebug(300002) << "Unable to open CLucene index for repo '" << name() << "': " << m_index->lastError();
00163         delete m_index;
00164         delete m_model;
00165         m_index = 0;
00166         m_model = 0;
00167 
00168         m_state = CLOSED;
00169         emit opened( this, false );
00170         return;
00171     }
00172 #else
00173     setParentModel( m_model );
00174 #endif
00175 
00176     // check if we have to convert
00177     // =================================
00178     bool convertingData = false;
00179 
00180     // if the backend changed we convert
00181     // in case only the storage dir changes we normally would not have to convert but
00182     // it is just simpler this way
00183     if ( oldBackendName != backend->pluginName() ||
00184          oldBasePath.isEmpty() ) {
00185 
00186         kDebug() << "Previous backend:" << oldBackendName << "- new backend:" << backend->pluginName();
00187         kDebug() << "Old path:" << oldBasePath << "- new path:" << m_basePath;
00188 
00189         if ( oldBasePath.isEmpty() ) {
00190             // backward comp: empty string means old storage path
00191             // and before we stored the data directly in the default basePath
00192             m_oldStoragePath = createStoragePath( name() );
00193         }
00194         else {
00195             m_oldStoragePath = m_basePath + "data/" + oldBackendName;
00196         }
00197 
00198         // try creating a model for the old storage
00199         Soprano::Model* oldModel = 0;
00200         m_oldStorageBackend = Soprano::discoverBackendByName( oldBackendName );
00201         if ( m_oldStorageBackend ) {
00202             // FIXME: even if there is no old data we still create a model here which results in a new empty db!
00203             oldModel = m_oldStorageBackend->createModel( QList<Soprano::BackendSetting>() << Soprano::BackendSetting( Soprano::BackendOptionStorageDir, m_oldStoragePath ) );
00204         }
00205 
00206         if ( oldModel ) {
00207             if ( !oldModel->isEmpty() ) {
00208                 kDebug() << "Starting model conversion";
00209 
00210                 convertingData = true;
00211                 // No need to use the index filter as it already contains the data
00212                 ModelCopyJob* copyJob = new ModelCopyJob( oldModel, m_model, this );
00213                 connect( copyJob, SIGNAL( result( KJob* ) ), this, SLOT( copyFinished( KJob* ) ) );
00214                 copyJob->start();
00215             }
00216             else {
00217                 m_state = OPEN;
00218                 emit opened( this, true );
00219             }
00220         }
00221         else {
00222             // FIXME: inform the user
00223             kDebug( 300002 ) << "Unable to convert old model.";
00224             m_state = OPEN;
00225             emit opened( this, true );
00226         }
00227     }
00228     else {
00229         kDebug() << "no need to convert" << name();
00230         m_state = OPEN;
00231         emit opened( this, true );
00232     }
00233 
00234 
00235     // save the settings
00236     // =================================
00237     // do not save when converting yet. If converting is cancelled we would loose data.
00238     // this way conversion is restarted the next time
00239     if ( !convertingData ) {
00240         repoConfig.writeEntry( "Used Soprano Backend", backend->pluginName() );
00241         repoConfig.writePathEntry( "Storage Dir", m_basePath );
00242         repoConfig.sync(); // even if we crash the model has been created
00243     }
00244 }
00245 
00246 
00247 void Nepomuk::Repository::copyFinished( KJob* job )
00248 {
00249     if ( job->error() ) {
00250         // FIXME: inform the user
00251         kDebug( 300002 ) << "Converting old model failed.";
00252     }
00253     else {
00254         kDebug() << "Successfully converted model data for repo" << name();
00255 
00256         // delete the old model
00257         ModelCopyJob* copyJob = qobject_cast<ModelCopyJob*>( job );
00258         delete copyJob->source();
00259 
00260         // cleanup the actual data
00261         m_oldStorageBackend->deleteModelData( QList<Soprano::BackendSetting>() << Soprano::BackendSetting( Soprano::BackendOptionStorageDir, m_oldStoragePath ) );
00262 
00263         // save our new settings
00264         KConfigGroup repoConfig = KSharedConfig::openConfig( "nepomukserverrc" )->group( name() + " Settings" );
00265         repoConfig.writeEntry( "Used Soprano Backend", activeSopranoBackend()->pluginName() );
00266         repoConfig.writePathEntry( "Storage Dir", m_basePath );
00267         repoConfig.sync();
00268     }
00269 
00270     // although converting might have failed, the new model is open anyway
00271     m_state = OPEN;
00272     emit opened( this, true );
00273 }
00274 
00275 
00276 const Soprano::Backend* Nepomuk::Repository::activeSopranoBackend()
00277 {
00278     QString backendName = KSharedConfig::openConfig( "nepomukserverrc" )->group( "Basic Settings" ).readEntry( "Soprano Backend", "sesame2" );
00279     const Soprano::Backend* backend = ::Soprano::discoverBackendByName( backendName );
00280     if ( !backend ) {
00281         kDebug(300002) << "(Nepomuk::Core::Core) could not find backend" << backendName << ". Falling back to default.";
00282         backend = ::Soprano::usedBackend();
00283     }
00284     if ( !backend ) {
00285         kDebug(300002) << "(Nepomuk::Core::Core) could not find a backend.";
00286     }
00287     return backend;
00288 }
00289 
00290 #include "repository.moc"

NepomukDaemons

Skip menu "NepomukDaemons"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KCMShell
  • KNotify
  • KStyles
  • Nepomuk Daemons
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal