You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2009/06/30 21:28:12 UTC

svn commit: r789891 - /felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java

Author: rickhall
Date: Tue Jun 30 19:28:11 2009
New Revision: 789891

URL: http://svn.apache.org/viewvc?rev=789891&view=rev
Log:
Use bundle lock for system bundle operations instead of the "this"
lock. (FELIX-1287)

Modified:
    felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java

Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=789891&r1=789890&r2=789891&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Tue Jun 30 19:28:11 2009
@@ -123,7 +123,7 @@
 
     // Shutdown thread.
     private Thread m_shutdownThread = null;
-    private ThreadGate m_shutdownGate = null;
+    private volatile ThreadGate m_shutdownGate = null;
 
     /**
      * <p>
@@ -473,182 +473,190 @@
      *
      * @throws org.osgi.framework.BundleException if any error occurs.
     **/
-    public synchronized void init() throws BundleException
+    public void init() throws BundleException
     {
         // The system bundle can only be initialized if it currently isn't started.
-        final int state = getState();
-        if ((state == Bundle.INSTALLED) || (state == Bundle.RESOLVED))
+        acquireBundleLock(this,
+            Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE);
+        try
         {
-            // Get any system bundle activators.
-            m_activatorList = (List) m_configMutableMap.get(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP);
-            m_activatorList = (m_activatorList == null) ? new ArrayList() : new ArrayList(m_activatorList);
-
-            // Initialize event dispatcher.
-            m_dispatcher = EventDispatcher.start(m_logger);
-
-            // Create the bundle cache, if necessary, so that we can reload any
-            // installed bundles.
-            m_cache = (BundleCache) m_configMutableMap.get(
-                FelixConstants.FRAMEWORK_BUNDLECACHE_IMPL);
-            if (m_cache == null)
-            {
-                   try
-                   {
-                       m_cache = new BundleCache(m_logger, m_configMap);
-                   }
-                   catch (Exception ex)
-                   {
-                       m_logger.log(Logger.LOG_ERROR, "Error creating bundle cache.", ex);
-                       throw new BundleException("Error creating bundle cache.", ex);
-                   }
-            }
-
-            // If this is the first time init is called, check to see if
-            // we need to flush the bundle cache.
-            if (state == Bundle.INSTALLED)
-            {
-                String flush = (String) m_configMap.get(Constants.FRAMEWORK_STORAGE_CLEAN);
-                if ((flush != null)
-                    && flush.equalsIgnoreCase(Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT))
-                {
-                    try
-                    {
-                        m_cache.flush();
-                    }
-                    catch (Exception ex)
+            if ((getState() == Bundle.INSTALLED) || (getState() == Bundle.RESOLVED))
+            {
+                // Get any system bundle activators.
+                m_activatorList = (List) m_configMutableMap.get(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP);
+                m_activatorList = (m_activatorList == null) ? new ArrayList() : new ArrayList(m_activatorList);
+
+                // Initialize event dispatcher.
+                m_dispatcher = EventDispatcher.start(m_logger);
+
+                // Create the bundle cache, if necessary, so that we can reload any
+                // installed bundles.
+                m_cache = (BundleCache) m_configMutableMap.get(
+                    FelixConstants.FRAMEWORK_BUNDLECACHE_IMPL);
+                if (m_cache == null)
+                {
+                       try
+                       {
+                           m_cache = new BundleCache(m_logger, m_configMap);
+                       }
+                       catch (Exception ex)
+                       {
+                           m_logger.log(Logger.LOG_ERROR, "Error creating bundle cache.", ex);
+                           throw new BundleException("Error creating bundle cache.", ex);
+                       }
+                }
+
+                // If this is the first time init is called, check to see if
+                // we need to flush the bundle cache.
+                if (getState() == Bundle.INSTALLED)
+                {
+                    String flush = (String) m_configMap.get(Constants.FRAMEWORK_STORAGE_CLEAN);
+                    if ((flush != null)
+                        && flush.equalsIgnoreCase(Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT))
                     {
-                        throw new BundleException("Unable to flush bundle cache.", ex);
+                        try
+                        {
+                            m_cache.flush();
+                        }
+                        catch (Exception ex)
+                        {
+                            throw new BundleException("Unable to flush bundle cache.", ex);
+                        }
                     }
                 }
-            }
 
-            // Initialize installed bundle data structures.
-            m_installedBundleMap = new HashMap();
-            m_installedBundleIndex = new TreeMap();
+                // Initialize installed bundle data structures.
+                m_installedBundleMap = new HashMap();
+                m_installedBundleIndex = new TreeMap();
+
+                // Add the system bundle to the set of installed bundles.
+                m_installedBundleMap.put(_getLocation(), this);
+                m_installedBundleIndex.put(new Long(0), this);
 
-            // Add the system bundle to the set of installed bundles.
-            m_installedBundleMap.put(_getLocation(), this);
-            m_installedBundleIndex.put(new Long(0), this);
-
-            // Manually resolve the system bundle, which will cause its
-            // state to be set to RESOLVED.
-            try
-            {
-                m_felixResolver.resolve(getCurrentModule());
-            }
-            catch (ResolveException ex)
-            {
-                // This should never happen.
-                throw new BundleException(
-                    "Unresolved constraint in System Bundle:"
-                    + ex.getRequirement());
-            }
+                // Manually resolve the system bundle, which will cause its
+                // state to be set to RESOLVED.
+                try
+                {
+                    m_felixResolver.resolve(getCurrentModule());
+                }
+                catch (ResolveException ex)
+                {
+                    // This should never happen.
+                    throw new BundleException(
+                        "Unresolved constraint in System Bundle:"
+                        + ex.getRequirement());
+                }
 
-            // Reload the cached bundles before creating and starting the
-            // system bundle, since we want all cached bundles to be reloaded
-            // when we activate the system bundle and any subsequent system
-            // bundle activators passed into the framework constructor.
-            BundleArchive[] archives = null;
+                // Reload the cached bundles before creating and starting the
+                // system bundle, since we want all cached bundles to be reloaded
+                // when we activate the system bundle and any subsequent system
+                // bundle activators passed into the framework constructor.
+                BundleArchive[] archives = null;
 
-            // First get cached bundle identifiers.
-            try
-            {
-                archives = m_cache.getArchives();
-            }
-            catch (Exception ex)
-            {
-                m_logger.log(Logger.LOG_ERROR, "Unable to list saved bundles.", ex);
-                archives = null;
-            }
-
-            // Now load all cached bundles.
-            for (int i = 0; (archives != null) && (i < archives.length); i++)
-            {
+                // First get cached bundle identifiers.
                 try
                 {
-                    // Keep track of the max bundle ID currently in use since we
-                    // will need to use this as our next bundle ID value if the
-                    // persisted value cannot be read.
-                    m_nextId = Math.max(m_nextId, archives[i].getId() + 1);
-
-                    // It is possible that a bundle in the cache was previously
-                    // uninstalled, but not completely deleted (perhaps because
-                    // of a crash or a locked file), so if we see an archive
-                    // with an UNINSTALLED persistent state, then try to remove
-                    // it now.
-                    if (archives[i].getPersistentState() == Bundle.UNINSTALLED)
-                    {
-                        m_cache.remove(archives[i]);
-                    }
-                    // Otherwise re-install the cached bundle.
-                    else
-                    {
-                        // Install the cached bundle.
-                        installBundle(archives[i].getId(), archives[i].getLocation(), null);
-                    }
+                    archives = m_cache.getArchives();
                 }
                 catch (Exception ex)
                 {
-ex.printStackTrace();
-                    fireFrameworkEvent(FrameworkEvent.ERROR, this, ex);
+                    m_logger.log(Logger.LOG_ERROR, "Unable to list saved bundles.", ex);
+                    archives = null;
+                }
+
+                // Now load all cached bundles.
+                for (int i = 0; (archives != null) && (i < archives.length); i++)
+                {
                     try
                     {
-                        m_logger.log(
-                            Logger.LOG_ERROR,
-                            "Unable to re-install " + archives[i].getLocation(),
-                            ex);
+                        // Keep track of the max bundle ID currently in use since we
+                        // will need to use this as our next bundle ID value if the
+                        // persisted value cannot be read.
+                        m_nextId = Math.max(m_nextId, archives[i].getId() + 1);
+
+                        // It is possible that a bundle in the cache was previously
+                        // uninstalled, but not completely deleted (perhaps because
+                        // of a crash or a locked file), so if we see an archive
+                        // with an UNINSTALLED persistent state, then try to remove
+                        // it now.
+                        if (archives[i].getPersistentState() == Bundle.UNINSTALLED)
+                        {
+                            m_cache.remove(archives[i]);
+                        }
+                        // Otherwise re-install the cached bundle.
+                        else
+                        {
+                            // Install the cached bundle.
+                            installBundle(archives[i].getId(), archives[i].getLocation(), null);
+                        }
                     }
-                    catch (Exception ex2)
+                    catch (Exception ex)
                     {
-                        m_logger.log(
-                            Logger.LOG_ERROR,
-                            "Unable to re-install cached bundle.",
-                            ex);
+ex.printStackTrace();
+                        fireFrameworkEvent(FrameworkEvent.ERROR, this, ex);
+                        try
+                        {
+                            m_logger.log(
+                                Logger.LOG_ERROR,
+                                "Unable to re-install " + archives[i].getLocation(),
+                                ex);
+                        }
+                        catch (Exception ex2)
+                        {
+                            m_logger.log(
+                                Logger.LOG_ERROR,
+                                "Unable to re-install cached bundle.",
+                                ex);
+                        }
+                        // TODO: FRAMEWORK - Perhaps we should remove the cached bundle?
                     }
-                    // TODO: FRAMEWORK - Perhaps we should remove the cached bundle?
                 }
-            }
 
-            // Now that we have loaded all cached bundles and have determined the
-            // max bundle ID of cached bundles, we need to try to load the next
-            // bundle ID from persistent storage. In case of failure, we should
-            // keep the max value.
-            m_nextId = Math.max(m_nextId, loadNextId());
+                // Now that we have loaded all cached bundles and have determined the
+                // max bundle ID of cached bundles, we need to try to load the next
+                // bundle ID from persistent storage. In case of failure, we should
+                // keep the max value.
+                m_nextId = Math.max(m_nextId, loadNextId());
+
+                // Create service registry.
+                m_registry = new ServiceRegistry(m_logger, new ServiceRegistryCallbacks() {
+                    public void serviceChanged(ServiceEvent event, Dictionary oldProps)
+                    {
+                        fireServiceEvent(event, oldProps);
+                    }
+                });
+                m_dispatcher.setServiceRegistry(m_registry);
+
+                // The framework is now in its startup sequence.
+                setBundleStateAndNotify(this, Bundle.STARTING);
+
+                // Now it is possible for threads to wait for the framework to stop,
+                // so create a gate for that purpose.
+                m_shutdownGate = new ThreadGate();
 
-            // Create service registry.
-            m_registry = new ServiceRegistry(m_logger, new ServiceRegistryCallbacks() {
-                public void serviceChanged(ServiceEvent event, Dictionary oldProps)
+                // Create system bundle activator and bundle context so we can activate it.
+                setActivator(new SystemBundleActivator());
+                setBundleContext(new BundleContextImpl(m_logger, this, this));
+                try
                 {
-                    fireServiceEvent(event, oldProps);
+                    Felix.m_secureAction.startActivator(
+                        getActivator(), getBundleContext());
+                }
+                catch (Throwable ex)
+                {
+                    EventDispatcher.shutdown();
+                    m_logger.log(Logger.LOG_ERROR, "Unable to start system bundle.", ex);
+                    throw new RuntimeException("Unable to start system bundle.");
                 }
-            });
-            m_dispatcher.setServiceRegistry(m_registry);
-
-            // The framework is now in its startup sequence.
-            setBundleStateAndNotify(this, Bundle.STARTING);
 
-            // Now it is possible for threads to wait for the framework to stop,
-            // so create a gate for that purpose.
-            m_shutdownGate = new ThreadGate();
-
-            // Create system bundle activator and bundle context so we can activate it.
-            setActivator(new SystemBundleActivator());
-            setBundleContext(new BundleContextImpl(m_logger, this, this));
-            try
-            {
-                Felix.m_secureAction.startActivator(
-                    getActivator(), getBundleContext());
-            }
-            catch (Throwable ex)
-            {
-                EventDispatcher.shutdown();
-                m_logger.log(Logger.LOG_ERROR, "Unable to start system bundle.", ex);
-                throw new RuntimeException("Unable to start system bundle.");
+                // Now that the system bundle is successfully created we can give
+                // its bundle context to the logger so that it can track log services.
+                m_logger.setSystemBundleContext(getBundleContext());
             }
-
-            // Now that the system bundle is successfully created we can give
-            // its bundle context to the logger so that it can track log services.
-            m_logger.setSystemBundleContext(getBundleContext());
+        }
+        finally
+        {
+            releaseBundleLock(this);
         }
     }
 
@@ -665,7 +673,9 @@
     {
         int startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
 
-        synchronized (this)
+        acquireBundleLock(this,
+            Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE);
+        try
         {
             // Initialize if necessary.
             if ((getState() == Bundle.INSTALLED) || (getState() == Bundle.RESOLVED))
@@ -689,37 +699,38 @@
                         startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
                     }
                 }
-            }
-        }
 
-        // Set the start level using the start level service;
-        // this ensures that all start level requests are
-        // serialized.
-        StartLevel sl = null;
-        try
-        {
-            sl = (StartLevel) getService(
-                getBundle(0), getServiceReferences((BundleImpl) getBundle(0),
-                StartLevel.class.getName(), null, true)[0]);
-        }
-        catch (InvalidSyntaxException ex)
-        {
-            // Should never happen.
-        }
+                // Set the start level using the start level service;
+                // this ensures that all start level requests are
+                // serialized.
+                StartLevel sl = null;
+                try
+                {
+                    sl = (StartLevel) getService(
+                        getBundle(0), getServiceReferences((BundleImpl) getBundle(0),
+                        StartLevel.class.getName(), null, true)[0]);
+                }
+                catch (InvalidSyntaxException ex)
+                {
+                    // Should never happen.
+                }
 
-        if (sl instanceof StartLevelImpl)
-        {
-            ((StartLevelImpl) sl).setStartLevelAndWait(startLevel);
-        }
-        else
-        {
-            sl.setStartLevel(startLevel);
-        }
+                if (sl instanceof StartLevelImpl)
+                {
+                    ((StartLevelImpl) sl).setStartLevelAndWait(startLevel);
+                }
+                else
+                {
+                    sl.setStartLevel(startLevel);
+                }
 
-        synchronized (this)
+                // The framework is now running.
+                setBundleStateAndNotify(this, Bundle.ACTIVE);
+            }
+        }
+        finally
         {
-            // The framework is now running.
-            setBundleStateAndNotify(this, Bundle.ACTIVE);
+            releaseBundleLock(this);
         }
 
         // Fire started event for system bundle.
@@ -775,12 +786,8 @@
         }
 
         // If there is a gate, wait on it; otherwise, return immediately.
-        ThreadGate gate;
-        synchronized (this)
-        {
-            gate = m_shutdownGate;
-        }
-
+        // Grab a copy of the gate, since it is volatile.
+        ThreadGate gate = m_shutdownGate;
         if (gate != null)
         {
             gate.await(timeout);
@@ -4143,17 +4150,10 @@
 
         public void run()
         {
-            // First, start the framework shutdown, which will
-            // stop all bundles.
-            synchronized (Felix.this)
-            {
-                // Change framework state from active to stopping.
-                // If framework is not active, then just return.
-                if (getState() != Bundle.STOPPING)
-                {
-                    return;
-                }
-            }
+            // The state of the framework should be STOPPING, so
+            // acquire the bundle lock to verify it.
+            acquireBundleLock(Felix.this, Bundle.STOPPING);
+            releaseBundleLock(Felix.this);
 
             // Use the start level service to set the start level to zero
             // in order to stop all bundles in the framework. Since framework
@@ -4247,13 +4247,20 @@
             }
 
             // Set the framework state to resolved.
-            synchronized (Felix.this)
+            acquireBundleLock(Felix.this, Bundle.STOPPING);
+            try
             {
+                // Set the framework state to resolved and open
+                // the shutdown gate.
                 setBundleStateAndNotify(Felix.this, Bundle.RESOLVED);
                 m_shutdownGate.open();
                 m_shutdownGate = null;
                 m_shutdownThread = null;
             }
+            finally
+            {
+                releaseBundleLock(Felix.this);
+            }
         }
     }
 
@@ -4623,4 +4630,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file