Hi Vishesh,

I finally looked at the remove-proxy patch again and fixed it. Now the
only problem left is the design weirdness of ResourceData instances
deleting themselves.

The main thing I did was removing all calls to determineUri from
ResourceData and moving them into Resource. I did the same with load()
and store() which is actually not necessary. Maybe it would be cleaner
to move those back...

I did not look into the merging of load and determineUri yet. I think we
should do that in a separate patch only after we cleaned this one up.
Otherwise it is impossible to debug.

Cheers,
Sebastian

On 05/26/2010 12:52 PM, Vishesh Handa wrote:
> 
> 
> On Wed, May 26, 2010 at 3:13 PM, Sebastian Trüg <[email protected]
> <mailto:[email protected]>> wrote:
> 
>     On 05/26/2010 10:08 AM, Vishesh Handa wrote:
>     >     > 3. When checking if the the m_kickoffUri is a nie:url for a
>     resource.
>     >     > The nieUrl is assigned to be equal to the uri. This however
>     gets fixed
>     >     > in the load(). And nieUrl isn't used anywhere, so it doesn't
>     >     matter that
>     >     > much.
>     >
>     >     I suppose you mean this part:
>     >
>     >     if( it.next() ) {
>     >          QUrl uri = it["r"].uri();
>     >          if( uri.isEmpty() ) {
>     >             m_uri = m_kickoffUri;
>     >          }
>     >          else {
>     >             m_uri = uri;
>     >             m_nieUrl = uri;
>     >          }
>     >
>     >     The last two lines. AFAICT this is perfectly fine since in the
>     latter
>     >     case both nie:url and resource URI are equal.
>     >
>     >
>     > I respectfully disagree. :)
>     >
>     > The query used is this "select distinct ?r ?o where { { ?r nie:url
>     <uri>
>     > . } UNION { <uri> ?p ?o . }  } LIMIT 1". The case where ?r isn't empty
>     > is when the <uri> contains the nie:url and therefore ?r will
>     contain the
>     > resource uri.
> 
>     You are of course correct. It should be "m_nieUrl = m_kickoffUri"
>     instead. Agreed?
> 
> 
> Yup. :)
> 
> If you get the time could you please look at my horrible merge patch?
> 
> Thanks
> - Vishesh Handa
> 
>     Cheers,
>     Sebastian
> 
> 
Index: resourcemanager_p.h
===================================================================
--- resourcemanager_p.h (revision 1130392)
+++ resourcemanager_p.h (working copy)
@@ -97,7 +97,7 @@
          */
         ResourceData* data( const QUrl& uri, const QUrl& type );
 
-        bool dataCacheFull();
+        bool dataCacheFull() const;
 
         /**
          * Delete unused ResourceData objects from the cache.
@@ -115,6 +115,8 @@
          */
         void determineAllUris();
 
+        bool shouldBeDeleted( ResourceData * rd ) const;
+
         QList<ResourceData*> allResourceData();
         QList<ResourceData*> allResourceDataOfType( const QUrl& type );
         QList<ResourceData*> allResourceDataWithProperty( const QUrl& _uri, 
const Variant& v );
Index: resourcedata.cpp
===================================================================
--- resourcedata.cpp    (revision 1130802)
+++ resourcedata.cpp    (working copy)
@@ -60,7 +60,6 @@
       m_kickoffUri( uri ),
       m_mainType( type ),
       m_modificationMutex(QMutex::Recursive),
-      m_proxyData(0),
       m_cacheDirty(true),
       m_pimoThing(0),
       m_groundingOccurence(0),
@@ -102,71 +101,50 @@
 
 QUrl Nepomuk::ResourceData::uri() const
 {
-    if( m_proxyData )
-        return m_proxyData->uri();
     return m_uri;
 }
 
 
 QUrl Nepomuk::ResourceData::type()
 {
-    if( m_proxyData )
-        return m_proxyData->type();
-    load();
     return m_mainType;
 }
 
 
 QList<QUrl> Nepomuk::ResourceData::allTypes()
 {
-    if( m_proxyData )
-        return m_proxyData->allTypes();
-    load();
     return m_types;
 }
 
 
 void Nepomuk::ResourceData::setTypes( const QList<QUrl>& types )
 {
-    if( m_proxyData ) {
-        m_proxyData->setTypes( types );
-    }
-    else if ( store() ) {
-        QMutexLocker lock(&m_modificationMutex);
+    Q_ASSERT(!m_uri.isEmpty());
 
-        // reset types
-        m_types.clear();
-        m_mainType = Soprano::Vocabulary::RDFS::Resource();
+    QMutexLocker lock(&m_modificationMutex);
 
-        QList<Node> nodes;
-        // load types (and set maintype)
-        foreach( const QUrl& url, types ) {
-            loadType( url );
-            nodes << Node( url );
-        }
+    // reset types
+    m_types.clear();
+    m_mainType = Soprano::Vocabulary::RDFS::Resource();
 
-        // update the data store
-        MAINMODEL->updateProperty( m_uri, Soprano::Vocabulary::RDF::type(), 
nodes );
+    QList<Node> nodes;
+    // load types (and set maintype)
+    foreach( const QUrl& url, types ) {
+        loadType( url );
+        nodes << Node( url );
     }
+
+    // update the data store
+    MAINMODEL->updateProperty( m_uri, Soprano::Vocabulary::RDF::type(), nodes 
);
 }
 
 
 
 void Nepomuk::ResourceData::resetAll( bool isDelete )
 {
-    // reset proxy
-    bool hadProxy = false;
-    if( m_proxyData ) {
-        hadProxy = true;
-        if( !m_proxyData->deref() &&
-            rm()->dataCacheFull() )
-            delete m_proxyData;
-        m_proxyData = 0;
-    }
-
     // remove us from all caches (store() will re-insert us later if necessary)
     m_rm->mutex.lock();
-    if( !m_uri.isEmpty() && !hadProxy ) // if we had a proxy we were not in 
m_initializedData ourselves
+    if( !m_uri.isEmpty() )
         m_rm->m_initializedData.remove( m_uri );
     if( !m_kickoffUri.isEmpty() )
         m_rm->m_uriKickoffData.remove( m_kickoffUri );
@@ -197,23 +175,12 @@
 
 QHash<QUrl, Nepomuk::Variant> Nepomuk::ResourceData::allProperties()
 {
-    if( m_proxyData )
-        return m_proxyData->allProperties();
-
-    load();
-
     return m_cache;
 }
 
 
 bool Nepomuk::ResourceData::hasProperty( const QUrl& uri )
 {
-    if( m_proxyData )
-        return m_proxyData->hasProperty( uri );
-
-    if( !load() )
-        return false;
-
     QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri );
     if( it == m_cache.constEnd() )
         return false;
@@ -224,12 +191,6 @@
 
 bool Nepomuk::ResourceData::hasProperty( const QUrl& p, const Variant& v )
 {
-    if( m_proxyData )
-        return m_proxyData->hasProperty( p, v );
-
-    if( !load() )
-        return false;
-
     QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( p );
     if( it == m_cache.constEnd() )
         return false;
@@ -246,22 +207,20 @@
 
 bool Nepomuk::ResourceData::hasType( const QUrl& uri )
 {
-    if( m_proxyData )
-        return m_proxyData->hasType( uri );
-
-    load();
     return constHasType( uri );
 }
 
 
 bool Nepomuk::ResourceData::constHasType( const QUrl& uri ) const
 {
+    kDebug() << uri;
     // we need to protect the reading, too. setTypes may be triggered from 
another thread
     QMutexLocker lock(&m_modificationMutex);
 
     Types::Class requestedType( uri );
     for ( QList<QUrl>::const_iterator it = m_types.constBegin();
           it != m_types.constEnd(); ++it ) {
+        kDebug() << "m_types:" << *it;
         Types::Class availType( *it );
         if ( availType == requestedType ||
              availType.isSubClassOf( requestedType ) ) {
@@ -274,39 +233,17 @@
 
 Nepomuk::Variant Nepomuk::ResourceData::property( const QUrl& uri )
 {
-    if( m_proxyData )
-        return m_proxyData->property( uri );
+    // we need to protect the reading, too. load my be triggered from another 
thread's
+    // connection to a Soprano statement signal
+    QMutexLocker lock(&m_modificationMutex);
 
-    if ( load() ) {
-        // we need to protect the reading, too. load my be triggered from 
another thread's
-        // connection to a Soprano statement signal
-        QMutexLocker lock(&m_modificationMutex);
-
-        QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri );
-        if ( it == m_cache.constEnd() ) {
-            return Variant();
-        }
-        else {
-            return *it;
-        }
+    QHash<QUrl, Variant>::const_iterator it = m_cache.constFind( uri );
+    if ( it == m_cache.constEnd() ) {
+        return Variant();
     }
     else {
-        return Variant();
+        return *it;
     }
-
-//     Variant v;
-
-//     if ( determineUri() ) {
-//         Soprano::Model* model = m_rm->m_manager->mainModel();
-//         Soprano::StatementIterator it = model->listStatements( 
Soprano::Statement( m_uri, QUrl(uri), Soprano::Node() ) );
-
-//         while ( it.next() ) {
-//             Statement statement = *it;
-//             v.append( Variant::fromNode( statement.object() ) );
-//         }
-//         it.close();
-//     }
-//     return v;
 }
 
 
@@ -314,7 +251,7 @@
 {
     QMutexLocker lock(&m_modificationMutex);
 
-    if ( !determineUri() ) {
+    if ( m_uri.isEmpty() ) {
         QMutexLocker rmlock(&m_rm->mutex);
         // create a random URI and add us to the initialized data, i.e. make 
us "valid"
         m_uri = m_rm->m_manager->generateUniqueUri( QString() );
@@ -422,7 +359,7 @@
     if ( m_cacheDirty ) {
         m_cache.clear();
 
-        if ( determineUri() ) {
+        if ( m_uri.isValid() ) {
             Soprano::QueryResultIterator it = 
MAINMODEL->executeQuery(QString("select distinct ?p ?o where { "
                                                                               
"%1 ?p ?o . "
                                                                               
"}").arg(Soprano::Node::resourceToN3(m_uri)),
@@ -476,76 +413,70 @@
 void Nepomuk::ResourceData::setProperty( const QUrl& uri, const 
Nepomuk::Variant& value )
 {
     Q_ASSERT( uri.isValid() );
+    Q_ASSERT( m_uri.isValid() );
 
-    if( m_proxyData )
-        return m_proxyData->setProperty( uri, value );
-
     // step 0: make sure this resource is in the store
-    if ( store() ) {
-        QMutexLocker lock(&m_modificationMutex);
+    QMutexLocker lock(&m_modificationMutex);
 
-        QList<Node> valueNodes;
+    QList<Node> valueNodes;
 
-        // make sure resource values are in the store
-        if ( value.simpleType() == qMetaTypeId<Resource>() ) {
-            QList<Resource> l = value.toResourceList();
-            for( QList<Resource>::iterator resIt = l.begin(); resIt != 
l.end(); ++resIt ) {
-                resIt->m_data->store();
-            }
+    // make sure resource values are in the store
+    if ( value.simpleType() == qMetaTypeId<Resource>() ) {
+        QList<Resource> l = value.toResourceList();
+        for( QList<Resource>::iterator resIt = l.begin(); resIt != l.end(); 
++resIt ) {
+            resIt->m_data->store();
         }
+    }
 
-        // add the actual property statements
+    // add the actual property statements
 
-        // one-to-one Resource
-        if( value.isResource() ) {
-            valueNodes.append( value.toUrl() );
-        }
+    // one-to-one Resource
+    if( value.isResource() ) {
+        valueNodes.append( value.toUrl() );
+    }
 
-        // one-to-many Resource
-        else if( value.isResourceList() ) {
-            const QList<QUrl>& l = value.toUrlList();
-            for( QList<QUrl>::const_iterator resIt = l.constBegin(); resIt != 
l.constEnd(); ++resIt ) {
-                valueNodes.append( *resIt );
-            }
+    // one-to-many Resource
+    else if( value.isResourceList() ) {
+        const QList<QUrl>& l = value.toUrlList();
+        for( QList<QUrl>::const_iterator resIt = l.constBegin(); resIt != 
l.constEnd(); ++resIt ) {
+            valueNodes.append( *resIt );
         }
+    }
 
-        // one-to-many literals
-        else if( value.isList() ) {
-            valueNodes = Nepomuk::valuesToRDFNodes( value );
-        }
+    // one-to-many literals
+    else if( value.isList() ) {
+        valueNodes = Nepomuk::valuesToRDFNodes( value );
+    }
 
-        // one-to-one literal
-        else {
-            valueNodes.append( Nepomuk::valueToRDFNode( value ) );
-        }
+    // one-to-one literal
+    else {
+        valueNodes.append( Nepomuk::valueToRDFNode( value ) );
+    }
 
-        // update the cache for now
-        m_cache[uri] = value;
+    // update the cache for now
+    m_cache[uri] = value;
 
-        // update the store
-        MAINMODEL->updateProperty( m_uri, uri, valueNodes );
-    }
+    // update the store
+    MAINMODEL->updateProperty( m_uri, uri, valueNodes );
 }
 
 
 void Nepomuk::ResourceData::removeProperty( const QUrl& uri )
 {
     Q_ASSERT( uri.isValid() );
+    Q_ASSERT( m_uri.isValid() );
 
-    if( m_proxyData )
-        return m_proxyData->removeProperty( uri );
-
     QMutexLocker lock(&m_modificationMutex);
 
-    if ( determineUri() ) {
-        m_cache.remove( uri );
-        MAINMODEL->removeProperty( m_uri, uri );
-    }
+    m_cache.remove( uri );
+    MAINMODEL->removeProperty( m_uri, uri );
 }
 
 
 void Nepomuk::ResourceData::remove( bool recursive )
 {
+    Q_ASSERT( m_uri.isValid() );
+
     // trueg: there is one problem we somehow need to work around:
     // if we have a resource with URI X and indentifier Y and we
     // create two ResourceData objects, one from X and one from Y
@@ -558,19 +489,11 @@
     // That way the proxy handling will take care of the rest.
     m_rm->determineAllUris();
 
-    if( m_proxyData ) {
-        m_proxyData->remove( recursive );
-    }
-    else {
-        QMutexLocker lock(&m_modificationMutex);
+    QMutexLocker lock(&m_modificationMutex);
 
-
-        if ( determineUri() ) {
-            MAINMODEL->removeAllStatements( Statement( m_uri, Node(), Node() ) 
);
-            if ( recursive ) {
-                MAINMODEL->removeAllStatements( Statement( Node(), Node(), 
m_uri ) );
-            }
-        }
+    MAINMODEL->removeAllStatements( Statement( m_uri, Node(), Node() ) );
+    if ( recursive ) {
+        MAINMODEL->removeAllStatements( Statement( Node(), Node(), m_uri ) );
     }
 
     resetAll();
@@ -579,179 +502,185 @@
 
 bool Nepomuk::ResourceData::exists()
 {
-    if( m_proxyData )
-        return m_proxyData->exists();
-
-    if( determineUri() ) {
+    if( m_uri.isValid() ) {
         return MAINMODEL->containsAnyStatement( Statement( m_uri, Node(), 
Node() ) );
     }
-    else
+    else {
         return false;
+    }
 }
 
 
 bool Nepomuk::ResourceData::isValid() const
 {
-    if( m_proxyData )
-        return m_proxyData->isValid();
-
     return( !m_mainType.isEmpty() && ( !m_uri.isEmpty() || 
!m_kickoffUri.isEmpty() || !m_kickoffId.isEmpty() ) );
 }
 
 
 bool Nepomuk::ResourceData::determineUri()
 {
-    if( m_proxyData )
-        return m_proxyData->determineUri();
+    //
+    // Preconditions:
+    // 1. m_kickoffId is not a local file path or URL (use m_kickoffUri for 
that)
+    //
+    // Now for the hard part
+    // We have the following possible situations:
+    // 1. m_uri is already valid
+    //    -> simple, nothing to do
+    //
+    // 2. m_uri is not valid
+    //    -> we need to determine the URI
+    //
+    // 2.1. m_kickoffId is valid
+    // 2.1.1. m_kickoffId is a resource URI
+    //        -> use it as m_uri
+    // 2.1.2. m_kickoffId is a nao:identifier for r
+    //        -> use r as m_uri
+    // 2.1.3. m_kickoffId is not found
+    //        -> create new random m_uri and save m_kickoffId as nao:identifier
+    //
+    // 2.2. m_kickoffUri is valid
+    // 2.2.1. it is a file URL
+    // 2.2.1.1. it is nie:url for r
+    //          -> use r as m_uri
+    // 2.2.1.2. it points to a file on a removable device for which we have a 
filex:/ URL
+    //          -> use the r in r nie:url filex:/...
+    // 2.2.1.3. it is a file which is not an object in some nie:url relation
+    //          -> create new random m_uri and use kickoffUriOrId() as m_nieUrl
+    //
+    QMutexLocker lock(&m_determineUriMutex);
 
-    else {
-        //
-        // Preconditions:
-        // 1. m_kickoffId is not a local file path or URL (use m_kickoffUri 
for that)
-        //
-        // Now for the hard part
-        // We have the following possible situations:
-        // 1. m_uri is already valid
-        //    -> simple, nothing to do
-        //
-        // 2. m_uri is not valid
-        //    -> we need to determine the URI
-        //
-        // 2.1. m_kickoffId is valid
-        // 2.1.1. m_kickoffId is a resource URI
-        //        -> use it as m_uri
-        // 2.1.2. m_kickoffId is a nao:identifier for r
-        //        -> use r as m_uri
-        // 2.1.3. m_kickoffId is not found
-        //        -> create new random m_uri and save m_kickoffId as 
nao:identifier
-        //
-        // 2.2. m_kickoffUri is valid
-        // 2.2.1. it is a file URL
-        // 2.2.1.1. it is nie:url for r
-        //          -> use r as m_uri
-        // 2.2.1.2. it points to a file on a removable device for which we 
have a filex:/ URL
-        //          -> use the r in r nie:url filex:/...
-        // 2.2.1.3. it is a file which is not an object in some nie:url 
relation
-        //          -> create new random m_uri and use kickoffUriOrId() as 
m_nieUrl
-        //
-        QMutexLocker lock(&m_determineUriMutex);
+    if( m_uri.isEmpty() ) {
 
-        if( m_uri.isEmpty() ) {
+        Soprano::Model* model = MAINMODEL;
 
-            Soprano::Model* model = MAINMODEL;
-
-            if( !m_kickoffId.isEmpty() ) {
-                //
-                // The kickoffUriOrId is actually a URI
-                //
-                KUrl uriFromKickoffId(m_kickoffId);
-                if( model->containsAnyStatement( uriFromKickoffId, Node(), 
Node() )) {
-                    m_uri = uriFromKickoffId;
-                }
-
-                //
-                // Check if the kickoffUriOrId is a resource identifier or a 
resource URI
-                //
-                else {
-                    QString query = QString::fromLatin1("select distinct ?r ?o 
where { { ?r %1 %2 . } UNION { %3 ?p ?o . } . } LIMIT 1")
-                                    .arg( 
Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::identifier()) )
-                                    .arg( 
Soprano::Node::literalToN3(m_kickoffId) )
-                                    .arg( 
Soprano::Node::resourceToN3(KUrl(m_kickoffId)) );
-                    Soprano::QueryResultIterator it = model->executeQuery( 
query, Soprano::Query::QueryLanguageSparql );
-                    if( it.next() ) {
-                        m_uri = it["r"].uri();
-                        if( m_uri.isEmpty() ) {
-                            m_uri = KUrl(m_kickoffId);
-                        }
-                        it.close();
-                    }
-                }
+        if( !m_kickoffId.isEmpty() ) {
+            //
+            // The kickoffUriOrId is actually a URI
+            //
+            KUrl uriFromKickoffId(m_kickoffId);
+            if( model->containsAnyStatement( uriFromKickoffId, Node(), Node() 
)) {
+                m_uri = uriFromKickoffId;
             }
 
-            else if( !m_kickoffUri.isEmpty() ) {
-                //
-                // In one query determine if the URI is already used as 
resource URI or as
-                // nie:url
-                //
-                QString query = QString::fromLatin1("select distinct ?r ?o 
where { "
-                                                    "{ ?r %1 %2 . 
FILTER(?r!=%2) . } "
-                                                    "UNION "
-                                                    "{ %2 ?p ?o . } "
-                                                    "} LIMIT 1")
-                                .arg( 
Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NIE::url()) )
-                                .arg( 
Soprano::Node::resourceToN3(m_kickoffUri) );
+            //
+            // Check if the kickoffUriOrId is a resource identifier or a 
resource URI
+            //
+            else {
+                QString query = QString::fromLatin1("select distinct ?r ?o 
where { { ?r %1 %2 . } UNION { %3 ?p ?o . } . } LIMIT 1")
+                                .arg( 
Soprano::Node::resourceToN3(Soprano::Vocabulary::NAO::identifier()) )
+                                .arg( Soprano::Node::literalToN3(m_kickoffId) )
+                                .arg( 
Soprano::Node::resourceToN3(KUrl(m_kickoffId)) );
                 Soprano::QueryResultIterator it = model->executeQuery( query, 
Soprano::Query::QueryLanguageSparql );
                 if( it.next() ) {
-                    QUrl uri = it["r"].uri();
-                    if( uri.isEmpty() ) {
-                        m_uri = m_kickoffUri;
+                    m_uri = it["r"].uri();
+                    if( m_uri.isEmpty() ) {
+                        m_uri = KUrl(m_kickoffId);
                     }
-                    else {
-                        m_uri = uri;
-                        m_nieUrl = m_kickoffUri;
-                    }
                     it.close();
                 }
-                else if( m_kickoffUri.scheme() == QLatin1String("file") ) {
-                    //
-                    // This is the hard part: The file may still be saved 
using a filex:/ URL
-                    // We have to determine if that is the case. For that we 
need to look if the URL
-                    // starts with any of the mounted filesystems' mount paths 
and then reconstruct
-                    // the filex:/ URL. Since that is quite some work which 
involved Solid and, thus,
-                    // DBus calls we simply call the removable storage service 
directly.
-                    //
-                    // If there is no resource yet we create a new uri in 
store()
-                    //
+            }
+        }
 
-                    //
-                    // We create a new dbus connection to protect us from 
multi-thread related crashes.
-                    //
-                    KUrl resourceUri = QDBusReply<QString>( 
QDBusInterface(QLatin1String("org.kde.nepomuk.services.nepomukremovablestorageservice"),
-                                                                           
QLatin1String("/nepomukremovablestorageservice"),
-                                                                           
QLatin1String("org.kde.nepomuk.RemovableStorage"),
-                                                                           
DBusConnectionPool::threadConnection())
-                                                            .call( 
QLatin1String("resourceUriFromLocalFileUrl"),
-                                                                   
m_kickoffUri.url() ) ).value();
-                    if( !resourceUri.isEmpty() ) {
-                        m_uri = resourceUri;
-                    }
-
-                    m_nieUrl = m_kickoffUri;
-                }
-                else if( m_kickoffUri.scheme() == QLatin1String("nepomuk") ) {
-                    // for nepomuk URIs we simply use the kickoff URI as 
resource URI
+        else if( !m_kickoffUri.isEmpty() ) {
+            //
+            // In one query determine if the URI is already used as resource 
URI or as
+            // nie:url
+            //
+            QString query = QString::fromLatin1("select distinct ?r ?o where { 
"
+                                                "{ ?r %1 %2 . FILTER(?r!=%2) . 
} "
+                                                "UNION "
+                                                "{ %2 ?p ?o . } "
+                                                "} LIMIT 1")
+                            .arg( 
Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NIE::url()) )
+                            .arg( Soprano::Node::resourceToN3(m_kickoffUri) );
+            Soprano::QueryResultIterator it = model->executeQuery( query, 
Soprano::Query::QueryLanguageSparql );
+            if( it.next() ) {
+                QUrl uri = it["r"].uri();
+                if( uri.isEmpty() ) {
                     m_uri = m_kickoffUri;
                 }
                 else {
-                    // for everything else we use m_kickoffUri as nie:url with 
a new random m_uri
+                    m_uri = uri;
                     m_nieUrl = m_kickoffUri;
                 }
+                it.close();
             }
+            else if( m_kickoffUri.scheme() == QLatin1String("file") ) {
+                //
+                // This is the hard part: The file may still be saved using a 
filex:/ URL
+                // We have to determine if that is the case. For that we need 
to look if the URL
+                // starts with any of the mounted filesystems' mount paths and 
then reconstruct
+                // the filex:/ URL. Since that is quite some work which 
involved Solid and, thus,
+                // DBus calls we simply call the removable storage service 
directly.
+                //
+                // If there is no resource yet we create a new uri in store()
+                //
 
+                //
+                // We create a new dbus connection to protect us from 
multi-thread related crashes.
+                //
+                KUrl resourceUri = QDBusReply<QString>( 
QDBusInterface(QLatin1String("org.kde.nepomuk.services.nepomukremovablestorageservice"),
+                                                                       
QLatin1String("/nepomukremovablestorageservice"),
+                                                                       
QLatin1String("org.kde.nepomuk.RemovableStorage"),
+                                                                       
DBusConnectionPool::threadConnection())
+                                                        .call( 
QLatin1String("resourceUriFromLocalFileUrl"),
+                                                               
m_kickoffUri.url() ) ).value();
+                if( !resourceUri.isEmpty() ) {
+                    m_uri = resourceUri;
+                }
+
+                m_nieUrl = m_kickoffUri;
+            }
+            else if( m_kickoffUri.scheme() == QLatin1String("nepomuk") ) {
+                // for nepomuk URIs we simply use the kickoff URI as resource 
URI
+                m_uri = m_kickoffUri;
+            }
             else {
-                // no kickoff values. We will only create a new random URI in 
store()
-                return false;
+                // for everything else we use m_kickoffUri as nie:url with a 
new random m_uri
+                m_nieUrl = m_kickoffUri;
             }
+        }
 
-            //
-            // Move us to the final data hash now that the URI is known
-            //
-            if( !m_uri.isEmpty() ) {
-                QMutexLocker rmlock(&m_rm->mutex);
+        else {
+            // no kickoff values. We will only create a new random URI in 
store()
+            return false;
+        }
 
-                ResourceDataHash::iterator it = 
m_rm->m_initializedData.find(m_uri);
-                if( it == m_rm->m_initializedData.end() ) {
-                    m_rm->m_initializedData.insert( m_uri, this );
-                }
-                else {
-                    m_proxyData = it.value();
-                    m_proxyData->ref();
-                }
+        //
+        // Move us to the final data hash now that the URI is known
+        //
+        if( !m_uri.isEmpty() ) {
+            QMutexLocker rmlock(&m_rm->mutex);
+
+            ResourceDataHash::iterator it = 
m_rm->m_initializedData.find(m_uri);
+            if( it == m_rm->m_initializedData.end() ) {
+                m_rm->m_initializedData.insert( m_uri, this );
             }
+            else {
+                // As the ResourceData already exists in m_initializedData, we 
simply
+                // make all the the Resources which contain "this" 
ResourceData, point
+                // to the initialized ResourceData instead.
+                replaceWith( it.value() );
+            }
         }
+    }
 
-        return !m_uri.isEmpty();
+    return !m_uri.isEmpty();
+}
+
+
+void Nepomuk::ResourceData::replaceWith(Nepomuk::ResourceData* rd)
+{
+    foreach( Resource * res, m_resources) {
+        ResourceData * oldData = res->m_data;
+        if ( oldData && !oldData->deref( res ) && rm()->shouldBeDeleted( 
oldData ) )
+            delete oldData;
+
+        res->m_data = rd;
+        res->m_data->ref( res );
     }
+    delete this;
 }
 
 
@@ -770,7 +699,6 @@
 
 Nepomuk::Thing Nepomuk::ResourceData::pimoThing()
 {
-    load();
     if( !m_pimoThing ) {
         if( hasType( Vocabulary::PIMO::Thing() ) ) {
             kDebug() << "we are already a thing. Creating link to ourself" << 
m_uri << this;
@@ -796,17 +724,13 @@
 
 bool Nepomuk::ResourceData::operator==( const ResourceData& other ) const
 {
-    const ResourceData* that = this;
-    if( m_proxyData )
-        that = m_proxyData;
-
-    if( that == &other )
+    if( this == &other )
         return true;
 
-    return( that->m_uri == other.m_uri &&
-            that->m_mainType == other.m_mainType &&
-            that->m_kickoffUri == other.m_kickoffUri &&
-            that->m_kickoffId == other.m_kickoffId );
+    return( m_uri == other.m_uri &&
+            m_mainType == other.m_mainType &&
+            m_kickoffUri == other.m_kickoffUri &&
+            m_kickoffId == other.m_kickoffId );
 }
 
 
@@ -818,8 +742,7 @@
              m_uri.url(),
              m_mainType.toString())
         .arg(m_ref);
-    if(m_proxyData)
-        dbg << QLatin1String(", proxy: " ) << *m_proxyData;
+
     return dbg << QLatin1String("]");
 }
 
Index: resourcemanager.cpp
===================================================================
--- resourcemanager.cpp (revision 1130838)
+++ resourcemanager.cpp (working copy)
@@ -197,7 +197,7 @@
 }
 
 
-bool Nepomuk::ResourceManagerPrivate::dataCacheFull()
+bool Nepomuk::ResourceManagerPrivate::dataCacheFull() const
 {
     return dataCnt >= 1000;
 }
@@ -230,6 +230,17 @@
 }
 
 
+bool Nepomuk::ResourceManagerPrivate::shouldBeDeleted( ResourceData * rd ) 
const
+{
+    //
+    // We delete data objects in one of two cases:
+    // 1. They are not valid and as such not in one of the 
ResourceManagerPrivate kickoff lists
+    // 2. The cache is already full and we need to clean up
+    //
+    return( !rd->cnt() && ( !rd->isValid() || dataCacheFull() ));
+}
+
+
 void Nepomuk::ResourceManagerPrivate::_k_storageServiceInitialized( bool 
success )
 {
     if( success ) {
Index: resourcedata.h
===================================================================
--- resourcedata.h      (revision 1130392)
+++ resourcedata.h      (working copy)
@@ -37,6 +37,7 @@
 
 namespace Nepomuk {
 
+    class Resource;
     class ResourceManagerPrivate;
 
     class ResourceData
@@ -45,11 +46,16 @@
         explicit ResourceData( const QUrl& uri, const QString& kickoffId_, 
const QUrl& type_, ResourceManagerPrivate* rm );
         ~ResourceData();
 
-        inline bool ref() {
+        inline bool ref(Nepomuk::Resource* res) {
+            QMutexLocker lock(&m_resourcesMutex);
+            m_resources.push_back( res );
             return m_ref.ref();
         }
 
-        inline bool deref() {
+
+        inline bool deref(Nepomuk::Resource* res) {
+            QMutexLocker lock(&m_resourcesMutex);
+            m_resources.removeAll( res );
             return m_ref.deref();
         }
 
@@ -139,6 +145,10 @@
          * Searches for the resource in the Nepomuk store using m_kickoffId 
and m_kickoffUri.
          *
          * \returns true if the resource was found and m_uri is set, false 
otherwise.
+         *
+         * Caution: This method might delete this instance of ResourceData and 
replace it
+         * with another one in all referencing Resource instances. It should 
never be called
+         * from within ResourceData methods!
          */
         bool determineUri();
 
@@ -155,7 +165,7 @@
 
         ResourceManagerPrivate* rm() const { return m_rm; }
 
-        ResourceData* proxy() const { return m_proxyData; }
+        bool shouldBeDeleted() const;
 
     private:
         void loadType( const QUrl& type );
@@ -187,13 +197,15 @@
         QMutex m_determineUriMutex;
         mutable QMutex m_modificationMutex;
 
+        /// Contains a list of resources which contain this ResourceData
+        QList<Resource *> m_resources;
+        QMutex m_resourcesMutex;
+
         /**
-         * Used to virtually merge two data objects representing the same
-         * resource. This happens if the resource was once created using its
-         * actual URI and once via its ID. To prevent early loading we allow
-         * this scenario.
+         * Makes the m_data pointer of all the Resources in m_resources point 
to
+         * rd, instead of 'this'. Handles refernce counting as well.
          */
-        ResourceData* m_proxyData;
+        void replaceWith( ResourceData* rd );
 
         QHash<QUrl, Variant> m_cache;
         bool m_cacheDirty;
Index: resource.cpp
===================================================================
--- resource.cpp        (revision 1130818)
+++ resource.cpp        (working copy)
@@ -47,14 +47,16 @@
 Nepomuk::Resource::Resource()
 {
     m_data = ResourceManager::instance()->d->data( QUrl(), QUrl() );
-    m_data->ref();
+    if ( m_data )
+        m_data->ref( this );
 }
 
 
 Nepomuk::Resource::Resource( ResourceManager* manager )
 {
     m_data = manager->d->data( QUrl(), QUrl() );
-    m_data->ref();
+    if ( m_data )
+        m_data->ref( this );
 }
 
 
@@ -62,7 +64,7 @@
 {
     m_data = res.m_data;
     if ( m_data )
-        m_data->ref();
+        m_data->ref( this );
 }
 
 
@@ -70,7 +72,7 @@
 {
     m_data = ResourceManager::instance()->d->data( uri, type );
     if ( m_data )
-        m_data->ref();
+        m_data->ref( this );
 }
 
 
@@ -78,7 +80,7 @@
 {
     m_data = manager->d->data( uri, type );
     if ( m_data )
-        m_data->ref();
+        m_data->ref( this );
 }
 
 
@@ -86,7 +88,7 @@
 {
     m_data = ResourceManager::instance()->d->data( uri, type );
     if ( m_data )
-        m_data->ref();
+        m_data->ref( this );
 }
 
 
@@ -94,7 +96,7 @@
 {
     m_data = ResourceManager::instance()->d->data( uri, type );
     if ( m_data )
-        m_data->ref();
+        m_data->ref( this );
 }
 
 
@@ -102,7 +104,7 @@
 {
     m_data = manager->d->data( uri, type );
     if ( m_data )
-        m_data->ref();
+        m_data->ref( this );
 }
 
 
@@ -110,26 +112,16 @@
 {
     m_data = data;
     if ( m_data )
-        data->ref();
+        m_data->ref( this );
 }
 
 
 Nepomuk::Resource::~Resource()
 {
     if ( m_data ) {
-        if ( !m_data->deref() ) {
-            //
-            // We delete data objects in one of three cases:
-            // 1. They are not valid and as such not in one of the 
ResourceManagerPrivate kickoff lists
-            // 2. They have a proxy which is the actual thing to reuse later on
-            // 3. The cache is already full and we need to clean up
-            //
-            if ( !m_data->isValid() ||
-                 m_data->proxy() ||
-                 m_data->rm()->dataCacheFull() ) {
-                delete m_data;
-            }
-        }
+        m_data->deref( this );
+        if ( m_data->rm()->shouldBeDeleted( m_data ) )
+            delete m_data;
     }
 }
 
@@ -137,12 +129,12 @@
 Nepomuk::Resource& Nepomuk::Resource::operator=( const Resource& res )
 {
     if( m_data != res.m_data ) {
-        if ( m_data && !m_data->deref() && !m_data->isValid() ) {
+        if ( m_data && !m_data->deref( this ) && 
m_data->rm()->shouldBeDeleted( m_data ) ) {
             delete m_data;
         }
         m_data = res.m_data;
         if ( m_data )
-            m_data->ref();
+            m_data->ref( this );
     }
 
     return *this;
@@ -187,36 +179,33 @@
 
 QUrl Nepomuk::Resource::resourceType() const
 {
-    if ( m_data ) {
-        return m_data->type();
-    }
-    else {
-        return QUrl();
-    }
+    m_data->determineUri();
+    m_data->load();
+    return m_data->type();
 }
 
 
 QList<QUrl> Nepomuk::Resource::types() const
 {
-    if ( m_data ) {
-        return m_data->allTypes();
-    }
-    else {
-        return QList<QUrl>();
-    }
+    m_data->determineUri();
+    m_data->load();
+    return m_data->allTypes();
 }
 
 
 void Nepomuk::Resource::setTypes( const QList<QUrl>& types )
 {
-    if ( m_data )
+    m_data->determineUri();
+    if ( m_data->store() ) {
         m_data->setTypes( types );
+    }
 }
 
 
 void Nepomuk::Resource::addType( const QUrl& type )
 {
-    if ( m_data ) {
+    m_data->determineUri();
+    if ( m_data->store() ) {
         QList<QUrl> tl = types();
         if( !tl.contains( type ) )
             setTypes( tl << type );
@@ -226,7 +215,13 @@
 
 bool Nepomuk::Resource::hasType( const QUrl& typeUri ) const
 {
-    return m_data ? m_data->hasType( typeUri ) : false;
+    m_data->determineUri();
+    if ( m_data->load() ) {
+        return m_data->hasType( typeUri );
+    }
+    else {
+        return false;
+    }
 }
 
 
@@ -238,7 +233,8 @@
 
 QHash<QUrl, Nepomuk::Variant> Nepomuk::Resource::properties() const
 {
-    if ( m_data ) {
+    m_data->determineUri();
+    if ( m_data->load() ) {
         return m_data->allProperties();
     }
     else {
@@ -262,13 +258,25 @@
 
 bool Nepomuk::Resource::hasProperty( const QUrl& uri ) const
 {
-    return m_data ? m_data->hasProperty( uri ) : false;
+    m_data->determineUri();
+    if ( m_data->load() ) {
+        return m_data->hasProperty( uri );
+    }
+    else {
+        return false;
+    }
 }
 
 
 bool Nepomuk::Resource::hasProperty( const Types::Property& p, const Variant& 
v ) const
 {
-    return m_data ? m_data->hasProperty( p.uri(), v ) : false;
+    m_data->determineUri();
+    if ( m_data->load() ) {
+        return m_data->hasProperty( p.uri(), v );
+    }
+    else {
+        return false;
+    }
 }
 
 
@@ -286,7 +294,8 @@
 
 Nepomuk::Variant Nepomuk::Resource::property( const QUrl& uri ) const
 {
-    if ( m_data ) {
+    m_data->determineUri();
+    if ( m_data->load() ) {
         return m_data->property( uri );
     }
     else {
@@ -311,7 +320,8 @@
 
 void Nepomuk::Resource::setProperty( const QUrl& uri, const Nepomuk::Variant& 
value )
 {
-    if ( m_data ) {
+    m_data->determineUri();
+    if ( m_data->store() ) {
         m_data->setProperty( uri, value );
     }
 }
@@ -325,7 +335,7 @@
 
 void Nepomuk::Resource::removeProperty( const QUrl& uri )
 {
-    if ( m_data ) {
+    if ( m_data && m_data->determineUri() ) {
         m_data->removeProperty( uri );
     }
 }
@@ -333,19 +343,17 @@
 
 void Nepomuk::Resource::removeProperty( const QUrl& uri, const Variant& value )
 {
-    if ( m_data ) {
-        QList<Variant> vl = property( uri ).toVariantList();
-        foreach( const Variant& v, value.toVariantList() ) {
-            vl.removeAll( v );
-        }
-        setProperty( uri, Variant( vl ) );
+    QList<Variant> vl = property( uri ).toVariantList();
+    foreach( const Variant& v, value.toVariantList() ) {
+        vl.removeAll( v );
     }
+    setProperty( uri, Variant( vl ) );
 }
 
 
 void Nepomuk::Resource::remove()
 {
-    if ( m_data ) {
+    if ( m_data && m_data->determineUri() ) {
         m_data->remove();
     }
 }
@@ -353,7 +361,12 @@
 
 bool Nepomuk::Resource::exists() const
 {
-    return m_data ? m_data->exists() : false;
+    if ( m_data && m_data->determineUri() ) {
+        return m_data->exists();
+    }
+    else {
+        return false;
+    }
 }
 
 
@@ -478,7 +491,8 @@
 
 Nepomuk::Thing Nepomuk::Resource::pimoThing()
 {
-    if( m_data ) {
+    m_data->determineUri();
+    if( m_data->load() ) {
         return m_data->pimoThing();
     }
     else {
_______________________________________________
Nepomuk mailing list
[email protected]
https://mail.kde.org/mailman/listinfo/nepomuk

Reply via email to