Eliminate contention on ServiceRegistry.getServiceReferences(String, Filter) (FELIX-1783).

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@827818 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
index 76a0304..f1ba5fc 100644
--- a/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
+++ b/framework/src/main/java/org/apache/felix/framework/ServiceRegistry.java
@@ -30,7 +30,7 @@
     private final Logger m_logger;
     private long m_currentServiceId = 1L;
     // Maps bundle to an array of service registrations.
-    private Map m_serviceRegsMap = new HashMap();
+    private final Map m_serviceRegsMap = Collections.synchronizedMap(new HashMap());
     // Maps registration to thread to keep track when a
     // registration is in use, which will cause other
     // threads to wait.
@@ -50,17 +50,24 @@
         m_callbacks = callbacks;
     }
 
-    public synchronized ServiceReference[] getRegisteredServices(Bundle bundle)
+    public ServiceReference[] getRegisteredServices(Bundle bundle)
     {
         ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
         if (regs != null)
         {
-            ServiceReference[] refs = new ServiceReference[regs.length];
-            for (int i = 0; i < refs.length; i++)
+            List refs = new ArrayList(regs.length);
+            for (int i = 0; i < regs.length; i++)
             {
-                refs[i] = regs[i].getReference();
+                try
+                {
+                    refs.add(regs[i].getReference());
+                }
+                catch (IllegalStateException ex)
+                {
+                    // Don't include the reference as it is not valid anymore
+                }
             }
-            return refs;
+            return (ServiceReference[]) refs.toArray(new ServiceReference[refs.size()]);
         }
         return null;
     }
@@ -168,56 +175,64 @@
         }
     }
 
-    public synchronized List getServiceReferences(String className, Filter filter)
+    public List getServiceReferences(String className, Filter filter)
     {
         // Create a filtered list of service references.
         List list = new ArrayList();
 
+        Object[] registrations = m_serviceRegsMap.values().toArray();
+        
         // Iterator over all service registrations.
-        for (Iterator i = m_serviceRegsMap.entrySet().iterator(); i.hasNext(); )
+        for (int i = 0; i < registrations.length; i++)
         {
-            Map.Entry entry = (Map.Entry) i.next();
-            ServiceRegistration[] regs = (ServiceRegistration[]) entry.getValue();
+            ServiceRegistration[] regs = (ServiceRegistration[]) registrations[i];
 
             for (int regIdx = 0;
                 (regs != null) && (regIdx < regs.length);
                 regIdx++)
             {
-                // Determine if the registered services matches
-                // the search criteria.
-                boolean matched = false;
+                try
+                {
+                    // Determine if the registered services matches
+                    // the search criteria.
+                    boolean matched = false;
 
-                // If className is null, then look at filter only.
-                if ((className == null) &&
-                    ((filter == null) || filter.match(regs[regIdx].getReference())))
-                {
-                    matched = true;
-                }
-                // If className is not null, then first match the
-                // objectClass property before looking at the
-                // filter.
-                else if (className != null)
-                {
-                    String[] objectClass = (String[])
-                        ((ServiceRegistrationImpl) regs[regIdx])
-                            .getProperty(FelixConstants.OBJECTCLASS);
-                    for (int classIdx = 0;
-                        classIdx < objectClass.length;
-                        classIdx++)
+                    // If className is null, then look at filter only.
+                    if ((className == null) &&
+                        ((filter == null) || filter.match(regs[regIdx].getReference())))
                     {
-                        if (objectClass[classIdx].equals(className) &&
-                            ((filter == null) || filter.match(regs[regIdx].getReference())))
+                        matched = true;
+                    }
+                    // If className is not null, then first match the
+                    // objectClass property before looking at the
+                    // filter.
+                    else if (className != null)
+                    {
+                        String[] objectClass = (String[])
+                            ((ServiceRegistrationImpl) regs[regIdx])
+                                .getProperty(FelixConstants.OBJECTCLASS);
+                        for (int classIdx = 0;
+                            classIdx < objectClass.length;
+                            classIdx++)
                         {
-                            matched = true;
-                            break;
+                            if (objectClass[classIdx].equals(className) &&
+                                ((filter == null) || filter.match(regs[regIdx].getReference())))
+                            {
+                                matched = true;
+                                break;
+                            }
                         }
                     }
-                }
 
-                // Add reference if it was a match.
-                if (matched)
+                    // Add reference if it was a match.
+                    if (matched)
+                    {
+                        list.add(regs[regIdx].getReference());
+                    }
+                }
+                catch (IllegalStateException ex)
                 {
-                    list.add(regs[regIdx].getReference());
+                    // Don't include the reference as it is not valid anymore
                 }
             }
         }