• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

Nepomuk-Core

  • sources
  • kde-4.12
  • kdelibs
  • nepomuk-core
  • services
  • storage
repository.cpp
Go to the documentation of this file.
1 /*
2  *
3  * $Id: sourceheader 511311 2006-02-19 14:51:05Z trueg $
4  *
5  * This file is part of the Nepomuk KDE project.
6  * Copyright (C) 2006-2010 Sebastian Trueg <trueg@kde.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * See the file "COPYING" for the exact licensing terms.
13  */
14 
15 #include "repository.h"
16 #include "datamanagementmodel.h"
17 #include "datamanagementadaptor.h"
18 #include "classandpropertytree.h"
19 #include "virtuosoinferencemodel.h"
20 #include "ontologyloader.h"
21 
22 #include <Soprano/Backend>
23 #include <Soprano/PluginManager>
24 #include <Soprano/Global>
25 #include <Soprano/Version>
26 #include <Soprano/StorageModel>
27 #include <Soprano/QueryResultIterator>
28 #include <Soprano/Node>
29 #include <Soprano/Error/Error>
30 #include <Soprano/Vocabulary/RDF>
31 #include <Soprano/Vocabulary/NAO>
32 #include <Soprano/Vocabulary/NRL>
33 
34 #include <KStandardDirs>
35 #include <KDebug>
36 #include <KConfigGroup>
37 #include <KSharedConfig>
38 #include <KLocale>
39 #include <KNotification>
40 #include <KIcon>
41 #include <KIO/DeleteJob>
42 #include <kdbusconnectionpool.h>
43 
44 #include <QtCore/QTimer>
45 #include <QtCore/QFile>
46 #include <QtCore/QThread>
47 #include <QtCore/QCoreApplication>
48 #include <QtDBus/QDBusConnection>
49 
50 using namespace Soprano::Vocabulary;
51 
52 namespace {
53  QString createStoragePath( const QString& repositoryId )
54  {
55  return KStandardDirs::locateLocal( "data", "nepomuk/repository/" + repositoryId + '/' );
56  }
57 }
58 
59 
60 Nepomuk2::Repository::Repository( const QString& name )
61  : m_name( name ),
62  m_state( CLOSED ),
63  m_model( 0 ),
64  m_classAndPropertyTree( 0 ),
65  m_inferenceModel( 0 ),
66  m_dataManagementModel( 0 ),
67  m_dataManagementAdaptor( 0 ),
68  m_backend( 0 ),
69  m_ontologyLoader( 0 ),
70  m_port( 0 )
71 {
72  m_dummyModel = new Soprano::Util::DummyModel();
73 
74  connect( this, SIGNAL(opened(Repository*,bool)), this, SLOT(slotOpened(Repository*,bool)) );
75 }
76 
77 
78 Nepomuk2::Repository::~Repository()
79 {
80  kDebug() << m_name;
81  close();
82  delete m_dummyModel;
83 }
84 
85 
86 void Nepomuk2::Repository::close()
87 {
88  kDebug() << m_name;
89 
90  if( m_model ) {
91  emit closed(this);
92  }
93 
94  // delete DMS adaptor before anything else so we do not get requests while deleting the DMS
95  delete m_dataManagementAdaptor;
96  m_dataManagementAdaptor = 0;
97 
98  setParentModel(m_dummyModel);
99  delete m_dataManagementModel;
100  m_dataManagementModel = 0;
101 
102  delete m_inferenceModel;
103  m_inferenceModel = 0;
104 
105  delete m_classAndPropertyTree;
106  m_classAndPropertyTree = 0;
107 
108  delete m_model;
109  m_model = 0;
110 
111  delete m_ontologyLoader;
112  m_ontologyLoader = 0;
113 
114  m_state = CLOSED;
115 }
116 
117 
118 void Nepomuk2::Repository::open()
119 {
120  Q_ASSERT( m_state == CLOSED );
121 
122  m_state = OPENING;
123 
124  // get backend
125  // =================================
126  m_backend = Soprano::PluginManager::instance()->discoverBackendByName( QLatin1String( "virtuosobackend" ) );
127  if ( !m_backend ) {
128  KNotification::event( "failedToStart",
129  i18nc("@info - notification message",
130  "Nepomuk Semantic Desktop needs the Virtuoso RDF server to store its data. "
131  "Installing the Virtuoso Soprano plugin is mandatory for using Nepomuk." ),
132  KIcon( "application-exit" ).pixmap( 32, 32 ),
133  0,
134  KNotification::Persistent );
135  m_state = CLOSED;
136  emit opened( this, false );
137  return;
138  }
139  else if ( !m_backend->isAvailable() ) {
140  KNotification::event( "failedToStart",
141  i18nc("@info - notification message",
142  "Nepomuk Semantic Desktop needs the Virtuoso RDF server to store its data. "
143  "Installing the Virtuoso server and ODBC driver is mandatory for using Nepomuk." ),
144  KIcon( "application-exit" ).pixmap( 32, 32 ),
145  0,
146  KNotification::Persistent );
147  m_state = CLOSED;
148  emit opened( this, false );
149  return;
150  }
151 
152  // read config
153  // =================================
154  KConfigGroup repoConfig = KSharedConfig::openConfig( "nepomukserverrc" )->group( name() + " Settings" );
155  QString basePath = repoConfig.readPathEntry( "Storage Dir", QString() );
156 
157  if( basePath.isEmpty() ) {
158  m_basePath = createStoragePath(name());
159  // First time run
160  repoConfig.writeEntry("GraphMigrationRequired", false);
161  }
162  else {
163  m_basePath = basePath;
164  }
165  m_storagePath = m_basePath + "data/" + m_backend->pluginName();
166  Soprano::BackendSettings settings = readVirtuosoSettings();
167 
168  if ( !KStandardDirs::makeDir( m_storagePath ) ) {
169  kDebug() << "Failed to create storage folder" << m_storagePath;
170  m_state = CLOSED;
171  emit opened( this, false );
172  return;
173  }
174 
175  kDebug() << "opening repository '" << name() << "' at '" << m_basePath << "'";
176 
177  // WARNING:
178  // This is used as a hack to get the port number and virtuoso version number. This slot
179  // should not by async, as the values it sets are subsequently used.
180  // The QObject cast is because m_backend is const
181  QObject* qobj = dynamic_cast<QObject*>(const_cast<Soprano::Backend*>(m_backend));
182  connect( qobj, SIGNAL(virtuosoInitParameters(int, QString)),
183  this, SLOT(slotVirtuosoInitParameters(int,QString)) );
184 
185  // open storage
186  // =================================
187  Soprano::settingInSettings( settings, Soprano::BackendOptionStorageDir ).setValue( m_storagePath );
188  m_model = m_backend->createModel( settings );
189  if ( !m_model ) {
190  kDebug() << "Unable to create model for repository" << name();
191  kError() << m_backend->lastError();
192  m_state = CLOSED;
193  emit opened( this, false );
194  return;
195  }
196 
197  // We accept virtuoso version 6.1.6+ Nepomuk hasn't really been tested with 7
198  QRegExp regex("(6\\.1\\.[6789])");
199  if( !m_virtuosoVersion.contains(regex) ) {
200  kError() << "NepomukStorage only works with virtuoso 6.1.6 and beyond";
201  return;
202  }
203 
204  connect(m_model, SIGNAL(virtuosoStopped(bool)), this, SLOT(slotVirtuosoStopped(bool)));
205 
206  kDebug() << "Successfully created new model for repository" << name();
207 
208  // create the one class and property tree to be used in DMS
209  // =================================
210  m_classAndPropertyTree = new Nepomuk2::ClassAndPropertyTree(this);
211 
212  // Create the Inference model which enables Virtuoso inference
213  // =================================
214  m_inferenceModel = new VirtuosoInferenceModel(m_model);
215 
216  // Set the parent as the main model for now. Once the ontologies have been loaded it will
217  // be set to the data management model
218  setParentModel( m_model );
219 
220  // save the settings
221  repoConfig.writeEntry( "Used Soprano Backend", m_backend->pluginName() );
222  repoConfig.writePathEntry( "Storage Dir", m_basePath );
223  repoConfig.writeEntry( "Port", m_port );
224  repoConfig.sync(); // even if we crash the model has been created
225 
226  m_state = OPEN;
227  emit opened( this, true );
228 }
229 
230 
231 QString Nepomuk2::Repository::usedSopranoBackend() const
232 {
233  if ( m_backend )
234  return m_backend->pluginName();
235  else
236  return QString();
237 }
238 
239 
240 Soprano::BackendSettings Nepomuk2::Repository::readVirtuosoSettings() const
241 {
242  Soprano::BackendSettings settings;
243 
244  KConfigGroup repoConfig = KSharedConfig::openConfig( "nepomukserverrc" )->group( name() + " Settings" );
245  const int maxMem = repoConfig.readEntry( "Maximum memory", 50 );
246 
247  // below NumberOfBuffers=400 virtuoso crashes (at least on amd64)
248  settings << Soprano::BackendSetting( "buffers", qMax( 4, maxMem-30 )*100 );
249 
250  // make a checkpoint every 10 minutes to minimize the startup time
251  settings << Soprano::BackendSetting( "CheckpointInterval", 10 );
252 
253  // lower the minimum transaction log size to make sure the checkpoints are actually executed
254  settings << Soprano::BackendSetting( "MinAutoCheckpointSize", 200000 );
255 
256  // alwyays index literals
257  settings << Soprano::BackendSetting( "fulltextindex", "sync" );
258 
259  // Always force the start, ie. kill previously started Virtuoso instances
260  settings << Soprano::BackendSetting( "forcedstart", true );
261 
262  // 100 server threads is hopefully enough - at some point the problem of maximum server threads == max client
263  // needs to be addressed as well
264  settings << Soprano::BackendSetting( "ServerThreads", 100 );
265 
266  // we have our own notifications through the ResourceWatcher. Thus, we disable the statement signals
267  settings << Soprano::BackendSetting( "noStatementSignals", true );
268 
269  // We don't care as they screw up performance
270  settings << Soprano::BackendSetting( "fakeBooleans", false );
271  settings << Soprano::BackendSetting( "emptyGraphs", false );
272 
273  // Never take more than 5 minutes to answer a query (this is to filter out broken queries and bugs in Virtuoso's query optimizer)
274  // trueg: We cannot activate this yet. 1. Virtuoso < 6.3 crashes and 2. even open cursors are subject to the timeout which is really
275  // not what we want!
276 // settings << Soprano::BackendSetting( "QueryTimeout", 5*60000 );
277 
278  return settings;
279 }
280 
281 void Nepomuk2::Repository::slotOpened(Nepomuk2::Repository* , bool success)
282 {
283  if( !success ) {
284  emit loaded(this, false);
285  return;
286  }
287 
288  m_ontologyLoader = new OntologyLoader( this, this );
289  connect( m_ontologyLoader, SIGNAL(ontologyUpdateFinished(bool)),
290  this, SLOT(slotOntologiesLoaded(bool)) );
291  m_ontologyLoader->updateLocalOntologies();
292 }
293 
294 void Nepomuk2::Repository::slotOntologiesLoaded(bool somethingChanged)
295 {
296  updateInference(somethingChanged);
297  if( m_state == OPEN ) {
298  m_state = LOADED;
299  emit loaded(this, true);
300  }
301 }
302 
303 void Nepomuk2::Repository::updateInference(bool ontologiesChanged)
304 {
305  // Update the query prefixes
306  QHash<QString, QString> prefixes;
307 
308  QString query = QString::fromLatin1("select ?g ?abr where { ?r %1 ?g ; %2 ?abr . }")
309  .arg( Soprano::Node::resourceToN3( NAO::hasDefaultNamespace() ),
310  Soprano::Node::resourceToN3( NAO::hasDefaultNamespaceAbbreviation() ) );
311 
312  Soprano::QueryResultIterator it = executeQuery( query, Soprano::Query::QueryLanguageSparql );
313  while( it.next() ) {
314  QString ontology = it[0].toString();
315  QString prefix = it[1].toString();
316 
317  prefixes.insert( prefix, ontology );
318 
319  // The '2' is for the prefixes to be global
320  // http://docs.openlinksw.com/virtuoso/fn_xml_set_ns_decl.html
321  QString command = QString::fromLatin1("DB.DBA.XML_SET_NS_DECL( '%1', '%2', 2 )")
322  .arg( prefix, ontology );
323 
324  executeQuery( command, Soprano::Query::QueryLanguageUser, QLatin1String("sql") );
325  }
326 
327  // update the prefixes in the DMS adaptor for script convenience
328  if( m_dataManagementAdaptor )
329  m_dataManagementAdaptor->setPrefixes(prefixes);
330 
331  // update the rest
332  m_classAndPropertyTree->rebuildTree(this);
333  m_inferenceModel->updateOntologyGraphs(ontologiesChanged);
334 }
335 
336 void Nepomuk2::Repository::slotVirtuosoInitParameters(int port, const QString& version)
337 {
338  m_port = port;
339  m_virtuosoVersion = version;
340 }
341 
342 
343 void Nepomuk2::Repository::slotVirtuosoStopped(bool normalExit)
344 {
345  if(!normalExit) {
346  kDebug() << "Virtuoso was killed or crashed. Restarting the repository.";
347  // restart the dumb way for now
348  // Ideally we would inform the other services so they can be restarted or something.
349  close();
350  open();
351  }
352 }
353 
354 void Nepomuk2::Repository::closePublicInterface()
355 {
356  delete m_dataManagementAdaptor;
357  m_dataManagementAdaptor = 0;
358 
359  setParentModel( m_inferenceModel );
360  connect(m_model, SIGNAL(virtuosoStopped(bool)), this, SLOT(slotVirtuosoStopped(bool)));
361 
362  delete m_dataManagementModel;
363  m_dataManagementModel = 0;
364 }
365 
366 void Nepomuk2::Repository::openPublicInterface()
367 {
368  if( m_dataManagementModel && m_dataManagementAdaptor )
369  return;
370 
371  closePublicInterface();
372 
373  // =================================
374  // create the DataManagementModel on top of everything
375  m_dataManagementModel = new DataManagementModel(m_classAndPropertyTree, m_inferenceModel, this);
376  setParentModel(m_dataManagementModel);
377 
378  // setParentModel disconnects all signals from the previous parent
379  connect(m_model, SIGNAL(virtuosoStopped(bool)), this, SLOT(slotVirtuosoStopped(bool)));
380 
381  m_dataManagementAdaptor = new Nepomuk2::DataManagementAdaptor(m_dataManagementModel);
382 
383  QDBusConnection con = KDBusConnectionPool::threadConnection();
384  con.registerObject(QLatin1String("/datamanagement"), m_dataManagementAdaptor,
385  QDBusConnection::ExportScriptableContents);
386 }
387 
388 #include "repository.moc"
QHash
QObject
Nepomuk2::ClassAndPropertyTree
Definition: classandpropertytree.h:45
Nepomuk2::Repository::~Repository
~Repository()
Definition: repository.cpp:78
Nepomuk2::Repository::openPublicInterface
void openPublicInterface()
Registers the datamangement interface this is used to communicate with the rest of world...
Definition: repository.cpp:366
classandpropertytree.h
repository.h
Nepomuk2::Repository
Represents the main Nepomuk model.
Definition: repository.h:53
Nepomuk2::DataManagementAdaptor
Definition: datamanagementadaptor.h:47
Nepomuk2::VirtuosoInferenceModel
Definition: virtuosoinferencemodel.h:29
Nepomuk2::Repository::opened
void opened(Repository *, bool success)
Emitted when the Repository successfully opened.
Nepomuk2::Repository::usedSopranoBackend
QString usedSopranoBackend() const
Definition: repository.cpp:231
Nepomuk2::Repository::close
void close()
Definition: repository.cpp:86
virtuosoinferencemodel.h
ontologyloader.h
datamanagementmodel.h
Nepomuk2::Repository::closePublicInterface
void closePublicInterface()
Switches off the datamanagement interface that is used to communicate with the rest of the world...
Definition: repository.cpp:354
Nepomuk2::Repository::open
void open()
Will emit the opened signal.
Definition: repository.cpp:118
datamanagementadaptor.h
Nepomuk2::Repository::Repository
Repository(const QString &name)
Definition: repository.cpp:60
Nepomuk2::DataManagementModel
Definition: datamanagementmodel.h:39
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:48:08 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

Nepomuk-Core

Skip menu "Nepomuk-Core"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal