Ok, thanks for the feedback.

/pierre

Richard S. Hall wrote:
Yes, that does make sense. You are correct that the listeners are snapshot'ed, so in this case you are more likely to see your own event. However, there is no guarantee that someone else didn't sneak in and make a request to PackageAdmin before you could do it. :-(

But, assuming you know what is going on, I think this approach should be reasonably safe.

-> richard

On 4/10/09 1:57 PM, Pierre De Rop wrote:
I'm sorry, in the previous sample code, I forgot to remove the fwk listener after the refresh, so here is the good fix:

public class BundleInstaller {
 BundleContext _bctx;
 PackageAdmin _pkgAdmin;

 // ...
 void update(Bundle[] bundles) {
   for (Bundle b : bundles) {
     b.stop();
     b.update();
   }

   final CountDownLatch latch = new CountDownLatch(1);
   FrameworkListener listener = new FrameworkListener() {
       public void frameworkEvent(FrameworkEvent event) {
           if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
               latch.countDown();
           }
       }
   };

   _bctx.addFrameworkListener(listener);
   _pkgAdmin.refresh(null); // asynchronous
   latch.await();
   _bctx.removeFrameworkListener(listener);

   for (Bundle b : bundles) {
     b.start();
   }
 }
}

so, is it ok ?

/pierre



Pierre De Rop wrote:
I have looked into the code of the package admin implementation, from the trunk, and I think I have found a working solution for my problem. Indeed, in the org.apache.felix.deploymentadmin.spi.StartBundleCommand class, the method "execute" just does the following, when refreshing synchronously:

       context.addFrameworkListener(listener);
       packageAdmin.refreshPackages(null);
       m_refreshMonitor.waitForRefresh();
       context.removeFrameworkListener(listener);

So, the trick consists in registering/unregistering a fwk listener before/after refreshing/waiting ... It works because the Bundle.update() method fires the PACKAGES_REFRESHED event on a snapshot of the currently registered framework listeners.

So, now, instead of registering a global FrameworkListener, my BundleInstaller does the following, and it seems to work fine:

public class BundleInstaller {
 BundleContext _bctx;
 PackageAdmin _pkgAdmin;

 // ...
 void update(Bundle[] bundles) {
   for (Bundle b : bundles) {
     b.stop();
     b.update();
   }

   final CountDownLatch latch = new CountDownLatch(1);
   _bctx.addFrameworkListener(new FrameworkListener() {
         public void frameworkEvent(FrameworkEvent event) {
if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
                 latch.countDown();
             }
         }
   });

   _pkgAdmin.refresh(null); // asynchronous
   latch.await();

   for (Bundle b : bundles) {
     b.start();
   }
 }
}

Does this make sense ?

/pierre



Richard S. Hall wrote:
On 4/9/09 10:14 AM, Pierre De Rop wrote:
Hello everyone,

I just discovered that invoking Bundle.update() method may fire a framework event PACKAGES_REFRESHED event. In the trunk, I see, in Felix.java, line 1691, that the "update" method may invoke the refreshPackage(null) method, which then fires the event.

To be clear, it only invokes refreshPackages() on the bundle being updated, not all bundles.

I understand this issue this causes for you, but I am not sure of a solution. We could possibly add a configuration to turn off auto-refreshing, but this would really just tie you to Felix since other implementations may still auto-refresh.

What you really need is for the call to refreshPackages() to return some sort of request ID so you can check for when your request is finished.

-> richard

Is is a normal behavior ?
So far, I was fairly certain that this event was only fired after invoking PackageAdmin.refreshPackages() methods. Actually, we are using our own bundle installer, which install/updates our bundles. And our bundle installer does the following, when it updates a bundle:

class BundleInstaller implements FrameworkListener {
 boolean refreshing = false;

 void update(Bundle([] bundles) {
   for (Bundle b : bundles) {
      b.stop();
      b.update(); // May fire a PACKAGES_REFRESHED event
   }

   synchronized (this) {
     this.refreshing = true;
   }
   *packageAdmin.refresh(null); // asynchronous *

   synchronized (this) {
*while (refreshing) wait(); *// ensure that all bundles are refreshed before restarting updated bundles.
   }

   for (Bundle b : bundles) {
      b.start();
   }
 }

 // Here, I listen to the framework event "PACKAGES_REFRESHED"
 void frameworkEvent(FrameworkEvent event) {
    switch (event.getType()) {
       case FrameworkEvent.PACKAGES_REFRESHED:
       synchronized (this) {
          this.refreshing = false;
          notify();
       }
     }
 }
}

The problem here, is that the first loop of my method "update" invokes Bundle.update(), which may fire some unexpected PACKAGES_REFRESHED events ... I'm expecting only one, and my waiting loop exits after the first event received.

So, what can I do in order to ensure that the PackageAdmin.refreshPackages(null) method has completed ?

Thanks in advance;
/pierre





---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
For additional commands, e-mail: users-h...@felix.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
For additional commands, e-mail: users-h...@felix.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
For additional commands, e-mail: users-h...@felix.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
For additional commands, e-mail: users-h...@felix.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
For additional commands, e-mail: users-h...@felix.apache.org

Reply via email to