You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by rw...@apache.org on 2012/12/16 17:51:05 UTC

svn commit: r1422628 - in /stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl: SolrFieldMapper.java SolrQueryFactory.java SolrYard.java

Author: rwesten
Date: Sun Dec 16 16:51:04 2012
New Revision: 1422628

URL: http://svn.apache.org/viewvc?rev=1422628&view=rev
Log:
fix for STANBOL-844; also some improvements to the SolrFieldMapper (logging, read/write lock instead of syncronized)

Modified:
    stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrFieldMapper.java
    stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrQueryFactory.java
    stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrYard.java

Modified: stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrFieldMapper.java
URL: http://svn.apache.org/viewvc/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrFieldMapper.java?rev=1422628&r1=1422627&r2=1422628&view=diff
==============================================================================
--- stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrFieldMapper.java (original)
+++ stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrFieldMapper.java Sun Dec 16 16:51:04 2012
@@ -37,6 +37,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.Map.Entry;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServer;
@@ -45,6 +46,7 @@ import org.apache.solr.client.solrj.resp
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
+import org.apache.stanbol.commons.namespaceprefix.NamespacePrefixService;
 import org.apache.stanbol.commons.solr.utils.SolrUtil;
 import org.apache.stanbol.entityhub.servicesapi.defaults.NamespaceEnum;
 import org.apache.stanbol.entityhub.servicesapi.defaults.SpecialFieldEnum;
@@ -135,12 +137,15 @@ public class SolrFieldMapper implements 
     private final Map<String,IndexField> fieldMappings = 
             //STANBOL-669: LRU chaches MUST BE synchronized!
             Collections.synchronizedMap(new LRU<String,IndexField>());
+    
+    private NamespacePrefixService nsPrefixService;
 
-    public SolrFieldMapper(SolrServer server) {
+    public SolrFieldMapper(SolrServer server, NamespacePrefixService nps) {
         if (server == null) {
             log.warn("NULL parsed as SolrServer: Loading and Saving of the Namespace Prefix Settings will be deactivated!");
             log.warn("  This is OK for Unit Test but should not happen in productive use!");
         }
+        this.nsPrefixService = nps;
         this.server = server;
     }
 
@@ -602,12 +607,23 @@ public class SolrFieldMapper implements 
      * @return the map holding the namespace to prefix mappings
      */
     private Map<String,String> getNamespaceMap() {
-        if (__namespaceMap == null) {
-            synchronized (prefixNamespaceMappingsLock) {
-                loadNamespaceConfig();
+        prefixNamespaceMappingsLock.readLock().lock();
+        Map<String,String> m = __namespaceMap;
+        prefixNamespaceMappingsLock.readLock().unlock();
+        if (m == null) {
+            prefixNamespaceMappingsLock.writeLock().lock();
+            try {
+                m = __namespaceMap; //might be concurrently be initialised
+                if(m == null){
+                    loadNamespaceConfig();
+                    m = __namespaceMap;
+                }
+            } finally {
+                prefixNamespaceMappingsLock.writeLock().unlock();
             }
+            
         }
-        return __namespaceMap;
+        return m;
     }
 
     /**
@@ -618,7 +634,7 @@ public class SolrFieldMapper implements 
      * used as lock during loading of the namespace <-> prefix mappings
      * (fixes STANBOL-668)
      */
-    private Object prefixNamespaceMappingsLock = new Object();
+    private ReentrantReadWriteLock prefixNamespaceMappingsLock = new ReentrantReadWriteLock();
 
     /**
      * Getter for the prefix to namespace mappings
@@ -626,12 +642,22 @@ public class SolrFieldMapper implements 
      * @return the map holding the prefix to namespace mappings
      */
     private Map<String,String> getPrefixMap() {
-        if (__prefixMap == null) {
-            synchronized (prefixNamespaceMappingsLock) {
-                loadNamespaceConfig();
+        prefixNamespaceMappingsLock.readLock().lock();
+        Map<String,String> m = __prefixMap;
+        prefixNamespaceMappingsLock.readLock().unlock();
+        if (m == null) {
+            prefixNamespaceMappingsLock.writeLock().lock();
+            try {
+                m = __prefixMap; //might be concurrently be initialised
+                if(m == null){
+                    loadNamespaceConfig();
+                    m = __prefixMap;
+                }
+            } finally {
+                prefixNamespaceMappingsLock.writeLock().unlock();
             }
         }
-        return __prefixMap;
+        return m;
     }
 
     /**
@@ -667,6 +693,8 @@ public class SolrFieldMapper implements 
             if (namespace != null) {
                 return namespace + shortFieldName.substring(seperatorIndex + 1);
             } else {
+                log.error("Unknown prefix {} used by Field {}",prefix,shortFieldName);
+                log.error("known prefixes: {}",getPrefixMap());
                 throw new IllegalStateException("Unknown prefix " + prefix + " (parsed from field "
                                                 + shortFieldName + ")!");
             }
@@ -698,13 +726,26 @@ public class SolrFieldMapper implements 
         if (namespace == null) {
             return null;
         }
-        Map<String,String> prefixMap = getPrefixMap();
-        String prefix = getNamespaceMap().get(namespace);
+        Map<String,String> namespaceMap = getNamespaceMap();
+        String prefix = namespaceMap.get(namespace);
         if (prefix != null) {
             return prefix;
         } else if (create) { // only if not present and prefix is true
-            NamespaceEnum defaultMapping = NamespaceEnum.forNamespace(namespace);
-            if (defaultMapping != null && !prefixMap.containsKey(defaultMapping.getPrefix())) {
+            prefixNamespaceMappingsLock.writeLock().lock();
+            try {
+                //try again to get the prefix ... there might be a concurrent change
+                prefix = getNamespaceMap().get(namespace);
+                if(prefix != null){ //added by an other thread
+                    return prefix; //nothing else to do
+                }
+                Map<String,String> prefixMap = getPrefixMap();
+                String defaultprefix;
+                if(nsPrefixService != null){
+                    defaultprefix = nsPrefixService.getPrefix(namespace);
+                } else {
+                    NamespaceEnum defaultMapping = NamespaceEnum.forNamespace(namespace);
+                    defaultprefix = defaultMapping != null ? defaultMapping.getPrefix() : null;
+                }
                 /*
                  * NOTE: we need to check here also if the default prefix is not yet taken, because the Solr
                  * Index used to store the prefixes might be older than the latest change within the
@@ -712,20 +753,26 @@ public class SolrFieldMapper implements 
                  * Enum is already assigned to a different namespace within the Solr index! In such cases, we
                  * need to create a new prefix for this namespace
                  */
-                prefix = defaultMapping.getPrefix();
-            } else {
-                // need to generate a default mapping
-                prefix = createPrefix(prefixMap);
-            }
-            addNamespaceMapping(prefix, namespace); // we need to add the new mapping
-            saveNamespaceConfig(); // save the configuration
-            //make sure the namespaces are committed to the Solr Server
-            try {
-                server.commit();
-            } catch (SolrServerException e) {
-                log.error("Unable to commit NamespaceConfig to SolrServer",e);
-            } catch (IOException e) {
-                log.error("Unable to commit NamespaceConfig to SolrServer",e);
+                if (defaultprefix != null && !prefixMap.containsKey(defaultprefix)) {
+                    prefix = defaultprefix;
+                } else { // need to generate a default mapping
+                    prefix = createPrefix(prefixMap);
+                }
+                //add an namespace
+                log.debug("add namespace prefix '{}' for '{}'",prefix,namespace);
+                prefixMap.put(prefix, namespace);
+                namespaceMap.put(namespace, prefix);
+                saveNamespaceConfig(); // save the configuration
+                //make sure the namespaces are committed to the Solr Server
+                try {
+                    server.commit();
+                } catch (SolrServerException e) {
+                    log.error("Unable to commit NamespaceConfig to SolrServer",e);
+                } catch (IOException e) {
+                    log.error("Unable to commit NamespaceConfig to SolrServer",e);
+                }
+            } finally {
+                prefixNamespaceMappingsLock.writeLock().unlock();
             }
         }
         return prefix; // may return null if !create
@@ -737,24 +784,24 @@ public class SolrFieldMapper implements 
              // NamespaceEnum
             defaultNsPrefixNumber++;
             defaultPrefix = DEFAULT_NS_PREFIX_STRING + defaultNsPrefixNumber;
-        } while (prefixMap.containsKey(defaultPrefix) || NamespaceEnum.forPrefix(defaultPrefix) != null);
+        } while (prefixMap.containsKey(defaultPrefix) || 
+                NamespaceEnum.forPrefix(defaultPrefix) != null ||
+                (nsPrefixService != null && nsPrefixService.getNamespace(defaultPrefix) != null));
         return defaultPrefix;
     }
 
-    private void addNamespaceMapping(String prefix, String namespace) {
-        synchronized (prefixNamespaceMappingsLock) { 
-            getPrefixMap().put(prefix, namespace);
-            getNamespaceMap().put(namespace, prefix);
-        }
-    }
-
     /**
      * Leads the prefix to namespace mappings from the configured Solr server and inits the two mapps holding
-     * the prefix &lt;-&gt; namespace mappings
+     * the prefix &lt;-&gt; namespace mappings.<p>
+     * Needs to be called under a write lock on {@link #prefixNamespaceMappingsLock}
      */
     private void loadNamespaceConfig() {
-        HashMap<String,String> prefixMap = new HashMap<String,String>();
-        HashMap<String,String> namespaceMap = new HashMap<String,String>();
+        log.debug("loadNamespaceConfig for {}",server);
+        if(__prefixMap != null || __namespaceMap != null){
+            log.warn("LoadNamespaceConfig called while mapping maps are NOT NULL!");
+        }
+        __prefixMap = new HashMap<String,String>();
+        __namespaceMap = new HashMap<String,String>();
         SolrDocument config = null;
         try {
             config = getSolrDocument(FieldMapper.URI);
@@ -773,14 +820,14 @@ public class SolrFieldMapper implements 
                         String prefix = configFieldElements[1];
                         Object value = config.getFirstValue(fieldName);
                         if (value != null) {
-                            if (namespaceMap.containsKey(value.toString())) {
-                                log.error("found two prefixes (" + namespaceMap.get(value.toString())
+                            if (__namespaceMap.containsKey(value.toString())) {
+                                log.error("found two prefixes (" + __namespaceMap.get(value.toString())
                                           + " and " + prefix + ") for Namespace " + value.toString()
                                           + " keep the first one");
                             } else {
                                 log.debug(" > prefix: " + prefix + " value: " + value);
-                                prefixMap.put(prefix, value.toString());
-                                namespaceMap.put(value.toString(), prefix);
+                                __prefixMap.put(prefix, value.toString());
+                                __namespaceMap.put(value.toString(), prefix);
                                 // check for default NS
                                 if (prefix.startsWith(DEFAULT_NS_PREFIX_STRING)) {
                                     String prefixNumber = prefix.substring(DEFAULT_NS_PREFIX_STRING.length());
@@ -807,11 +854,6 @@ public class SolrFieldMapper implements 
                 }
             }
         }
-        //only store complete mappings to the member variables (STANBOL-668)
-        synchronized (prefixNamespaceMappingsLock) {
-            __prefixMap = prefixMap;
-            __namespaceMap = namespaceMap;
-        }
     }
 
     private String getConfigFieldName(String configName) {
@@ -823,22 +865,31 @@ public class SolrFieldMapper implements 
      * changes!
      */
     public void saveNamespaceConfig() {
-        Map<String,String> prefixMap = getPrefixMap();
-        SolrInputDocument inputDoc = new SolrInputDocument();
-        inputDoc.addField(getDocumentIdField(), FieldMapper.URI);
-        for (Entry<String,String> entry : prefixMap.entrySet()) {
-            inputDoc.addField(getConfigFieldName(entry.getKey()), entry.getValue());
-        }
         if(server != null){
+            prefixNamespaceMappingsLock.writeLock().lock();
             try {
-                server.add(inputDoc);
-            } catch (IOException e) {
-                log.error("Unable save Configuration to SolrProvider", e);
-            } catch (SolrServerException e) {
-                log.error("Unable save Configuration to SolrProvider", e);
-            } catch (SolrException e) {
-                log.error("Unable save Configuration to SolrProvider", e);
+                log.debug("saveNamespaceConfig on {}",server);
+                Map<String,String> prefixMap = getPrefixMap();
+                SolrInputDocument inputDoc = new SolrInputDocument();
+                inputDoc.addField(getDocumentIdField(), FieldMapper.URI);
+                for (Entry<String,String> entry : prefixMap.entrySet()) {
+                    log.debug("  > {}: {}",entry.getKey(),entry.getValue());
+                    inputDoc.addField(getConfigFieldName(entry.getKey()), entry.getValue());
+                }
+                try {
+                    server.add(inputDoc);
+                } catch (IOException e) {
+                    log.error("Unable save Configuration to SolrProvider", e);
+                } catch (SolrServerException e) {
+                    log.error("Unable save Configuration to SolrProvider", e);
+                } catch (SolrException e) {
+                    log.error("Unable save Configuration to SolrProvider", e);
+                }
+            } finally {
+                prefixNamespaceMappingsLock.writeLock().unlock();
             }
+        } else {
+            log.warn("Unable to save NamespaceCondig because no SolrServer is set");
         }
     }
 

Modified: stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrQueryFactory.java
URL: http://svn.apache.org/viewvc/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrQueryFactory.java?rev=1422628&r1=1422627&r2=1422628&view=diff
==============================================================================
--- stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrQueryFactory.java (original)
+++ stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrQueryFactory.java Sun Dec 16 16:51:04 2012
@@ -931,20 +931,20 @@ public class SolrQueryFactory {
         // this.fieldConstraints.remove(constraintType);
         // }
     }
-    public static void main(String[] args) {
-        SolrQueryFactory factory = new SolrQueryFactory(
-            InMemoryValueFactory.getInstance(), 
-            IndexValueFactory.getInstance(), 
-            new SolrFieldMapper(null));
-        FieldQuery query = DefaultQueryFactory.getInstance().createFieldQuery();
-//        query.setConstraint("urn:field2", new TextConstraint("test","en","de"));
-        query.setConstraint("urn:field3", new TextConstraint(Arrays.asList(
-            "text value","anothertest","some more values"),"en","de",null));
-        query.addSelectedField("urn:field2a");
-        query.addSelectedField("urn:field3");
-        query.setLimit(5);
-        query.setOffset(5);
-        SolrQuery solrQuery = factory.parseFieldQuery(query, SELECT.QUERY);
-        System.out.println(solrQuery.getQuery());
-    }
+//    public static void main(String[] args) {
+//        SolrQueryFactory factory = new SolrQueryFactory(
+//            InMemoryValueFactory.getInstance(), 
+//            IndexValueFactory.getInstance(), 
+//            new SolrFieldMapper(null));
+//        FieldQuery query = DefaultQueryFactory.getInstance().createFieldQuery();
+////        query.setConstraint("urn:field2", new TextConstraint("test","en","de"));
+//        query.setConstraint("urn:field3", new TextConstraint(Arrays.asList(
+//            "text value","anothertest","some more values"),"en","de",null));
+//        query.addSelectedField("urn:field2a");
+//        query.addSelectedField("urn:field3");
+//        query.setLimit(5);
+//        query.setOffset(5);
+//        SolrQuery solrQuery = factory.parseFieldQuery(query, SELECT.QUERY);
+//        System.out.println(solrQuery.getQuery());
+//    }
 }

Modified: stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrYard.java
URL: http://svn.apache.org/viewvc/stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrYard.java?rev=1422628&r1=1422627&r2=1422628&view=diff
==============================================================================
--- stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrYard.java (original)
+++ stanbol/trunk/entityhub/yard/solr/src/main/java/org/apache/stanbol/entityhub/yard/solr/impl/SolrYard.java Sun Dec 16 16:51:04 2012
@@ -53,6 +53,7 @@ import org.apache.solr.client.solrj.resp
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.core.SolrCore;
+import org.apache.stanbol.commons.namespaceprefix.NamespacePrefixService;
 import org.apache.stanbol.commons.solr.IndexReference;
 import org.apache.stanbol.commons.solr.RegisteredSolrServerTracker;
 import org.apache.stanbol.commons.solr.managed.IndexMetadata;
@@ -302,6 +303,9 @@ public class SolrYard extends AbstractYa
         strategy=ReferenceStrategy.EVENT,
         policy=ReferencePolicy.DYNAMIC)
     private ManagedSolrServer managedSolrServer;
+    
+    @Reference(cardinality=ReferenceCardinality.OPTIONAL_UNARY)
+    private NamespacePrefixService nsPrefixService;
     /**
      * If update(..) and store(..) calls should be immediately committed.
      */
@@ -520,6 +524,7 @@ public class SolrYard extends AbstractYa
             if(server != null && !server.equals(this._server)){
                 //reset the fieldMapper so that it is reinitialised for the new one
                 //STANBOL-519
+                _server = server;
                 Lock writeLock = fieldMapperLock.writeLock();
                 writeLock.lock();
                 try {
@@ -536,6 +541,7 @@ public class SolrYard extends AbstractYa
         if(server != null){
             return server;
         } else {
+            _server = null;
             Lock writeLock = fieldMapperLock.writeLock();
             writeLock.lock();
             try {
@@ -729,8 +735,9 @@ public class SolrYard extends AbstractYa
         Lock writeLock = fieldMapperLock.writeLock();
         writeLock.lock();
         try {
-            // the fieldMapper need the Server to store it's namespace prefix configuration
-            _fieldMapper = new SolrFieldMapper(getServer());
+            if(_fieldMapper == null){ //might be init by an other thread
+                _fieldMapper = new SolrFieldMapper(getServer(), nsPrefixService);
+            }
             return _fieldMapper;
         } finally {
             writeLock.unlock();