• 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
  • libnepomukcore
  • resource
resourcemanager.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Nepomuk KDE project.
3  * Copyright (C) 2006-2012 Sebastian Trueg <trueg@kde.org>
4  * Copyright (C) 2010-2012 Vishesh Handa <handa.vish@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "resourcemanager.h"
23 #include "resourcemanager_p.h"
24 #include "resourcedata.h"
25 #include "tools.h"
26 #include "nepomukmainmodel.h"
27 #include "resource.h"
28 #include "class.h"
29 #include "nie.h"
30 #include "dbustypes.h"
31 #include "resourcewatcher.h"
32 
33 #include <kglobal.h>
34 #include <kdebug.h>
35 #include <krandom.h>
36 
37 #include <Soprano/Node>
38 #include <Soprano/Statement>
39 #include <Soprano/Vocabulary/RDF>
40 #include <Soprano/StatementIterator>
41 #include <Soprano/QueryResultIterator>
42 
43 #include <QtCore/QFileInfo>
44 #include <QtCore/QMutex>
45 #include <QtCore/QMutexLocker>
46 #include <QtCore/QUuid>
47 #include <QtCore/QMutableHashIterator>
48 #include <QtCore/QCoreApplication>
49 #include <QtDBus/QDBusConnection>
50 #include <QtDBus/QDBusConnectionInterface>
51 #include <QtDBus/QDBusServiceWatcher>
52 #include <QtDBus/QDBusMetaType>
53 
54 using namespace Soprano;
55 using namespace Soprano::Vocabulary;
56 using namespace Nepomuk2::Vocabulary;
57 
58 Nepomuk2::ResourceManager* Nepomuk2::ResourceManager::s_instance = 0;
59 
60 Nepomuk2::ResourceManagerPrivate::ResourceManagerPrivate( ResourceManager* manager )
61  : mainModel( 0 ),
62  overrideModel( 0 ),
63  mutex(QMutex::Recursive),
64  m_manager( manager ),
65  m_watcher( 0 )
66 {
67  Nepomuk2::DBus::registerDBusTypes();
68 }
69 
70 
71 Nepomuk2::ResourceData* Nepomuk2::ResourceManagerPrivate::data( const QUrl& uri, const QUrl& type )
72 {
73  if ( uri.isEmpty() ) {
74  // return an invalid resource which may be activated by calling setProperty
75  return new ResourceData( QUrl(), QUrl(), type, this );
76  }
77 
78  QUrl newUri = uri;
79  if( uri.scheme().isEmpty() ) {
80  const QString uriString = uri.toString();
81  if( uriString[0] == '/' && QFile::exists(uriString) ) {
82  newUri.setScheme(QLatin1String("file"));
83  }
84  }
85 
86  if( ResourceData* data = findData( newUri ) ) {
87  return data;
88  }
89  else {
90  if( uri.scheme() != QLatin1String("nepomuk") )
91  return new ResourceData( QUrl(), newUri, type, this );
92  else
93  return new ResourceData( newUri, QUrl(), type, this );
94  }
95 }
96 
97 
98 Nepomuk2::ResourceData* Nepomuk2::ResourceManagerPrivate::data( const QString& uriOrId, const QUrl& type )
99 {
100  if ( !uriOrId.isEmpty() ) {
101  KUrl url( uriOrId );
102  if( uriOrId[0] == '/' && QFile::exists(uriOrId) ) {
103  url.setScheme("file");
104  }
105  return data( url, type );
106  }
107 
108  return new ResourceData( QUrl(), QUrl(), type, this );
109 }
110 
111 
112 //FIXME: Streamline this function. It's supposed to be faster than the rest
113 Nepomuk2::ResourceData* Nepomuk2::ResourceManagerPrivate::dataForResourceUri( const QUrl& uri, const QUrl& type )
114 {
115  if ( uri.isEmpty() ) {
116  // return an invalid resource which may be activated by calling setProperty
117  return new ResourceData( QUrl(), QUrl(), type, this );
118  }
119 
120  if( ResourceData* data = findData( uri ) ) {
121  return data;
122  }
123  else {
124  return new ResourceData( uri, QUrl(), type, this );
125  }
126 }
127 
128 
129 QSet<Nepomuk2::ResourceData*> Nepomuk2::ResourceManagerPrivate::allResourceData()
130 {
131  return m_identifierKickOff.values().toSet() + m_urlKickOff.values().toSet() + m_initializedData.values().toSet();
132 }
133 
134 bool Nepomuk2::ResourceManagerPrivate::shouldBeDeleted( ResourceData * rd ) const
135 {
136  // We only delete ResourceData objects if no other Resource is accessing them
137  return !rd->cnt();
138 }
139 
140 
141 void Nepomuk2::ResourceManagerPrivate::_k_storageServiceInitialized( bool success )
142 {
143  if( success ) {
144  kDebug() << "Nepomuk Storage service up and initialized.";
145  m_manager->init();
146  emit m_manager->nepomukSystemStarted();
147  }
148  else {
149  _k_dbusServiceUnregistered( QLatin1String("org.kde.NepomukStorage") );
150  }
151 }
152 
153 
154 void Nepomuk2::ResourceManagerPrivate::_k_dbusServiceUnregistered( const QString& serviceName )
155 {
156  if( serviceName == QLatin1String("org.kde.NepomukStorage") ) {
157  kDebug() << "Nepomuk Storage service went down.";
158  if( m_manager->d->mainModel && m_manager->d->mainModel->isValid() ){
159  m_manager->d->mainModel->disconnect();
160  }
161  emit m_manager->nepomukSystemStopped();
162  }
163 }
164 
165 
166 
167 Nepomuk2::ResourceData* Nepomuk2::ResourceManagerPrivate::findData( const QUrl& uri )
168 {
169  if ( !uri.isEmpty() ) {
170  QMutexLocker lock( &mutex );
171 
172  if( uri.scheme() == QLatin1String("nepomuk") ) {
173  ResourceDataHash::iterator it = m_initializedData.find( uri );
174  if( it != m_initializedData.end() )
175  return it.value();
176  }
177  else if( uri.scheme().isEmpty() ) {
178  QString identifier = uri.toString();
179  QHash<QString, ResourceData*>::iterator it = m_identifierKickOff.find( identifier );
180  if( it != m_identifierKickOff.end() )
181  return it.value();
182  }
183  else {
184  QHash<QUrl, ResourceData*>::iterator it = m_urlKickOff.find( uri );
185  if( it != m_urlKickOff.end() )
186  return it.value();
187  }
188  }
189 
190  return 0;
191 }
192 
193 
194 Nepomuk2::ResourceManager::ResourceManager()
195  : QObject(),
196  d( new ResourceManagerPrivate( this ) )
197 {
198  // connect to the storage service's initialized signal to be able to emit
199  // the nepomukSystemStarted signal
200  QDBusConnection::sessionBus().connect( QLatin1String("org.kde.NepomukStorage"),
201  QLatin1String("/servicecontrol"),
202  QLatin1String("org.kde.nepomuk.ServiceControl"),
203  QLatin1String("serviceInitialized"),
204  this,
205  SLOT(_k_storageServiceInitialized(bool)) );
206 
207  // connect to the serviceUnregistered signal to be able to connect the nepomukSystemStopped
208  // signal once the storage service goes away
209  QDBusServiceWatcher *watcher = new QDBusServiceWatcher( QLatin1String("org.kde.NepomukStorage"),
210  QDBusConnection::sessionBus(),
211  QDBusServiceWatcher::WatchForUnregistration,
212  this );
213  connect( watcher, SIGNAL(serviceUnregistered(QString)),
214  this, SLOT(_k_dbusServiceUnregistered(QString)) );
215 
216  // now let's see if the service is already running and init, if so
217  QDBusMessage result = QDBusConnection::sessionBus().call(
218  QDBusMessage::createMethodCall(
219  QLatin1String("org.kde.NepomukStorage"),
220  QLatin1String("/servicecontrol"),
221  QLatin1String("org.kde.nepomuk.ServiceControl"),
222  QLatin1String("isInitialized")
223  )
224  );
225  if ( result.type() == QDBusMessage::ReplyMessage ) {
226  if ( result.arguments().count() > 0 ) {
227  const bool initialized = result.arguments()[0].toBool();
228  d->_k_storageServiceInitialized( initialized );
229  }
230  }
231 
232 }
233 
234 void Nepomuk2::ResourceManager::cleanupResources()
235 {
236  //
237  // Ideally, all three caches should be empty when the ResourceManager is being destroyed
238  // But that isn't always the case. There could be a Resource in a static object which gets
239  // deleted after the ResourceManager.
240  // In order to counter that case, we mark all Resource classes as invalid.
241  // The cache should be empty when the ResourceManager is getting destroyed
242  // See bug 292996 - https://bugs.kde.org/show_bug.cgi?id=292996
243  //
244  QMutexLocker lock( &d->mutex );
245  QList<ResourceData*> rdList = d->m_identifierKickOff.values() + d->m_urlKickOff.values() +
246  d->m_initializedData.values();
247  foreach( const ResourceData* rd, rdList.toSet() ) {
248  foreach(Resource* res, rd->resources())
249  res->m_data = 0;
250  delete rd;
251  }
252 }
253 
254 Nepomuk2::ResourceManager::~ResourceManager()
255 {
256  // The cache should be empty when the ResourceManager is getting destroyed
257  Q_ASSERT( d->m_identifierKickOff.isEmpty() );
258  Q_ASSERT( d->m_urlKickOff.isEmpty() );
259  Q_ASSERT( d->m_initializedData.isEmpty() );
260 
261  delete d->mainModel;
262  delete d;
263 
264  if(s_instance == this) {
265  s_instance = 0;
266  }
267 }
268 
269 
270 Nepomuk2::ResourceManager* Nepomuk2::ResourceManager::instance()
271 {
272  if(!s_instance) {
273  //
274  // This happens when QCoreApplication::quit has been called
275  //
276  QCoreApplication* app = QCoreApplication::instance();
277  if( !app )
278  return 0;
279 
280  s_instance = new ResourceManager();
281  s_instance->setParent( app );
282  connect( app, SIGNAL(aboutToQuit()), s_instance, SLOT(cleanupResources()) );
283  }
284  return s_instance;
285 }
286 
287 
288 int Nepomuk2::ResourceManager::init()
289 {
290  QMutexLocker lock( &d->initMutex );
291 
292  if( d->overrideModel ) {
293  return true;
294  }
295 
296  if( !d->mainModel ) {
297  d->mainModel = new MainModel( this );
298  }
299 
300  d->mainModel->init();
301 
302  return d->mainModel->isValid() ? 0 : -1;
303 }
304 
305 
306 bool Nepomuk2::ResourceManager::initialized() const
307 {
308  QMutexLocker lock( &d->initMutex );
309  if( d->overrideModel )
310  return true;
311 
312  return d->mainModel && d->mainModel->isValid();
313 }
314 
315 
316 void Nepomuk2::ResourceManager::removeResource( const QString& uri )
317 {
318  Resource res( uri );
319  res.remove();
320 }
321 
322 void Nepomuk2::ResourceManager::notifyError( const QString& uri, int errorCode )
323 {
324  kDebug() << "(Nepomuk2::ResourceManager) error: " << uri << " " << errorCode;
325  emit error( uri, errorCode );
326 }
327 
328 
329 QUrl Nepomuk2::ResourceManager::generateUniqueUri( const QString& name )
330 {
331  // default to res URIs
332  QString type = QLatin1String("res");
333 
334  // ctx is the only used value for name
335  if(name == QLatin1String("ctx")) {
336  type = name;
337  }
338 
339  Soprano::Model* model = mainModel();
340 
341  while( 1 ) {
342  QString uuid = QUuid::createUuid().toString();
343  uuid = uuid.mid(1, uuid.length()-2);
344  QString uriString = QLatin1String("nepomuk:/") + type + QLatin1String("/") + uuid;
345  QString query = QString::fromLatin1("select iri_to_id( '%1', 0 )").arg( uriString );
346 
347  Soprano::QueryResultIterator it = model->executeQuery( query, Soprano::Query::QueryLanguageUser,
348  QLatin1String("sql") );
349 
350  // don't loop forever if there was an error executing the query
351  if( model->lastError() ) {
352  return QUrl();
353  }
354  if( it.next() ) {
355  if( it[0].literal().toString().isEmpty() ) {
356  return QUrl( uriString );
357  }
358  }
359  }
360 }
361 
362 
363 Soprano::Model* Nepomuk2::ResourceManager::mainModel()
364 {
365  // make sure we are initialized
366  if ( !d->overrideModel && !initialized() ) {
367  init();
368  }
369 
370  if( d->overrideModel )
371  return d->overrideModel;
372 
373  return d->mainModel;
374 }
375 
376 
377 void Nepomuk2::ResourceManager::slotPropertyAdded(const Resource &res, const Types::Property &prop, const QVariant &value)
378 {
379  QMutexLocker lock( &d->mutex );
380  ResourceDataHash::iterator it = d->m_initializedData.find(res.uri());
381  if(it != d->m_initializedData.end()) {
382  ResourceData* data = *it;
383  data->propertyAdded(prop, value);
384  }
385 }
386 
387 void Nepomuk2::ResourceManager::slotPropertyRemoved(const Resource &res, const Types::Property &prop, const QVariant &value_)
388 {
389  QMutexLocker lock( &d->mutex );
390  ResourceDataHash::iterator it = d->m_initializedData.find(res.uri());
391  if(it != d->m_initializedData.end()) {
392  ResourceData* data = *it;
393  data->propertyRemoved(prop, value_);
394  }
395 }
396 
397 void Nepomuk2::ResourceManager::slotResourceRemoved(const QUrl& uri, const QList<QUrl>& )
398 {
399  QMutexLocker lock( &d->mutex );
400  ResourceDataHash::iterator it = d->m_initializedData.find(uri);
401  if(it != d->m_initializedData.end()) {
402  ResourceData* data = *it;
403  data->resetAll();
404  }
405  d->m_initializedData.remove(uri);
406 }
407 
408 
409 void Nepomuk2::ResourceManager::setOverrideMainModel( Soprano::Model* model )
410 {
411  QMutexLocker lock( &d->mutex );
412 
413  if( model != d->mainModel ) {
414  d->overrideModel = model;
415 
416  // clear cache to make sure we do not mix data
417  Q_FOREACH( ResourceData* data, d->allResourceData()) {
418  data->invalidateCache();
419  }
420  }
421 }
422 
423 void Nepomuk2::ResourceManagerPrivate::addToWatcher( const QUrl& uri )
424 {
425  if( uri.isEmpty() )
426  return;
427  // Lock the mutex, because the ResourceWatcher is not thread-safe.
428  // This should have a small impact, because a) it is not taking it for very long.
429  // b) the calling function in ResourceData will have to lock the mutex soon after this routine returns
430  // to edit m_initializedData, so there is limited opportunities for parallelism.
431  QMutexLocker lock( &mutex );
432  if( !m_watcher ) {
433  m_watcher = new ResourceWatcher(m_manager);
434  QObject::connect( m_watcher, SIGNAL(propertyAdded(Nepomuk2::Resource, Nepomuk2::Types::Property, QVariant)),
435  m_manager, SLOT(slotPropertyAdded(Nepomuk2::Resource, Nepomuk2::Types::Property, QVariant)) );
436  QObject::connect( m_watcher, SIGNAL(propertyRemoved(Nepomuk2::Resource, Nepomuk2::Types::Property, QVariant)),
437  m_manager, SLOT(slotPropertyRemoved(Nepomuk2::Resource, Nepomuk2::Types::Property, QVariant)) );
438  QObject::connect( m_watcher, SIGNAL(resourceRemoved(QUrl,QList<QUrl>)),
439  m_manager, SLOT(slotResourceRemoved(QUrl, QList<QUrl>)) );
440  }
441  m_watcher->addResource( uri );
442  // (re-)start the watcher in case this resource is the only one in the list of watched
443  if( m_watcher->resourceCount() <= 1 ) {
444  m_watcher->start();
445  }
446 }
447 
448 void Nepomuk2::ResourceManagerPrivate::removeFromWatcher( const QUrl& uri )
449 {
450  if( uri.isEmpty())
451  return;
452 
453  QMutexLocker lock( &mutex );
454  if( !m_watcher )
455  return;
456 
457  m_watcher->removeResource( uri );
458  // stop the watcher since we do not want to watch all changes in case there is no ResourceData left
459  if( !m_watcher->resourceCount() ) {
460  m_watcher->stop();
461  }
462 }
463 
464 #include "resourcemanager.moc"
Nepomuk2::Resource::remove
void remove()
Remove this resource completely.
Definition: resource.cpp:313
class.h
Nepomuk2::MainModel
The main Nepomuk data storage model.
Definition: nepomukmainmodel.h:62
QHash
Nepomuk2::ResourceManager::removeResource
void removeResource(const QString &uri)
Remove the resource denoted by uri completely.
Definition: resourcemanager.cpp:316
QObject
Nepomuk2::ResourceManager::setOverrideMainModel
void setOverrideMainModel(Soprano::Model *model)
Override the main model used for all storage.
Definition: resourcemanager.cpp:409
Nepomuk2::ResourceData::propertyAdded
void propertyAdded(const Types::Property &prop, const QVariant &value)
Definition: resourcedata.cpp:804
Nepomuk2::ResourceManager::notifyError
void notifyError(const QString &uri, int errorCode)
Definition: resourcemanager.cpp:322
Nepomuk2::ResourceManager::initialized
bool initialized() const
Definition: resourcemanager.cpp:306
resource.h
Nepomuk2::Types::Property
A property is a resource of type rdf:Property which relates a domain with a range.
Definition: libnepomukcore/types/property.h:52
Nepomuk2::ResourceManager::instance
static ResourceManager * instance()
Definition: resourcemanager.cpp:270
Nepomuk2::ResourceData::invalidateCache
void invalidateCache()
Definition: resourcedata.cpp:680
resourcemanager.h
Nepomuk2::ResourceWatcher
Selectively monitor the nepomuk repository for changes.
Definition: resourcewatcher.h:81
resourcedata.h
Nepomuk2::DBus::registerDBusTypes
void registerDBusTypes()
Definition: dbustypes.cpp:112
Nepomuk2::ResourceManager::init
int init()
Initialize the Nepomuk framework.
Definition: resourcemanager.cpp:288
nepomukmainmodel.h
Nepomuk2::ResourceManager
The ResourceManager is the central Nepomuk configuration point.
Definition: resourcemanager.h:55
tools.h
Nepomuk2::Resource
Resource is the central object type in Nepomuk.
Definition: resource.h:93
resourcewatcher.h
Nepomuk2::Resource::uri
QUrl uri() const
The URI of the resource, uniquely identifying it.
Definition: resource.cpp:166
Nepomuk2::ResourceManager::mainModel
Soprano::Model * mainModel()
Retrieve the main data storage model.
Definition: resourcemanager.cpp:363
Nepomuk2::ResourceManager::generateUniqueUri
QUrl generateUniqueUri(const QString &label)
Generates a unique URI that is not used in the store yet.
Definition: resourcemanager.cpp:329
dbustypes.h
Nepomuk2::ResourceData
Definition: resourcedata.h:42
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