rgrunber

No bug left unassigned

There’s something really satisfying about resolving and (especially) closing a ~2.5 year old bug. In this case it wasn’t a new feature or bug, but just better compliance with packaging guidelines regarding bundled libraries. Thanks to all those that helped out!

Extending the p2 Repository Format in Fedora

We ship a lot of OSGi bundles in Fedora.

$ repoquery --repofrompath=foo,http://kojipkgs.fedoraproject.org/repos/f21-build/latest/x86_64/ --repoid=foo -q --whatprovides "osgi(*)" | wc -l
693

We already allow packagers to have requirements based on the OSGi metadata to some extent. We’re supporting Require-Bundle in specfiles through use of the “osgi(…)” provide but even with this, building Eclipse plugins has always seemed like a giant hack, and even more so when compared to the latest Java Maven Packaging Examples. Building with Tycho requires that your OSGi dependencies be in a p2 repository (update site). We obviously can’t just point to the eclipse.org update sites for our Fedora builds since all of our dependencies must be from packages within the Fedora infrastructure that were built from sources. Initially the simplest way to achieve this was to look on the system for all OSGi bundles, publish them to a p2 repository, and then feed this directly into Tycho’s build target platform.

This approach certainly works (and that’s what the copy-platform-all script did) but it still requires performing the same steps every time one needs to feed OSGi bundles to Tycho or some other application that uses p2 repositories. The end-goal is to have tighter integration with tools like XMvn, and to make packaging an easier task. To do this we really need to have our system locations be recognized as p2 repositories so that we could also take advantage of p2 APIs.

When I got back from EclipseCon NA 2014, I started playing around with this idea of having filesystem directories being recognized as a p2 repository.

Imagine :

$ eclipse -application org.eclipse.equinox.p2.director -repository fedora:/usr/share/java/ -installIU org.swtchart

with the result being that ‘org.swtchart’ from somewhere in ‘/usr/share/java’ gets installed into the eclipse instance. This was easy to implement and fairly simple to integrate with Tycho so that we only inject a few system locations and get proper dependency resolution.

I’ve named this fedoraproject-p2 mainly because Fedora’s requirements are the driving force but I could see this being useful in many other cases.

This has been used for some time now on rawhide, and with the addition of things like the xmvn-p2-installer-plugin, it won’t be long until Eclipse plugin packaging will be drastically simpler.

Testing p2 the easy way, and the hard way

So you want to debug changes you’re making to p2 by launching in a child Eclipse process. Simple enough. If it works for other plugins, why not p2 ? Turns out, it can be a little tricky.

In my case I wanted to test out a shared installation while looking at what was going on in the SimpleProfileRegistry (methods like getProfile, containsProfile, and createSurrogateProfile).

Here’s what I needed to do in order to get that working :

In addition to the generated config.ini, I needed the following attributes set.

eclipse.p2.data.area=@config.dir/.p2
osgi.sharedConfiguration.area=file\:/usr/lib64/eclipse/configuration

(Note: Default p2 data area is defined in LaunchConfigurationHelper of org.eclipse.pde.launching)

PDE has its own special way of setting up the configuration for a child Eclipse, so you’ll need to copy over the folder of your shared profile as SelfHostingProfile.profile and rename all IDs in the profiles accordingly . After failing countless times to get the child Eclipse to detect the SDKProfile.profile, I realized PDE always looks for a profile ID of SelfHostingProfile.

(Note: Default profile ID is defined in LaunchConfigurationHelper of org.eclipse.pde.launching)

It turns out containsProfile is a very popular method. There’s a separate thread that begins setting up profile preferences using the ProfilePreferences class. This ends up calling the synchronized method, containsProfile, and ultimately blocks because p2’s AutomaticUpdateSchedueler has already entered it. From within containsProfile, we end up calling setupRepos as well to set up the metadata repositories. As you might imagine, this ends up calling ProfilePreferences and blocks on entering the preference node because the other thread is in there. Now we have a deadlock.

Solution : You need to insert a breakpoint just before the containsProfile call to avoid a deadlock between the ProfilePreferences job and the p2’s AutomaticUpdateScheduler job. Let the ProfilePreferences thread continue before proceeding into the AutomaticUpdateScheduler’s call to containsProfile.

If all the above is too much of a giant pain (I found it kind of fun), you can always just run the p2 Tests, to hopefully take some solace in the fact that you (probably) haven’t broken anything.

mvn -Declipse-sdk-repo.url=http://download.eclipse.org/eclipse/updates/4.4-I-builds -Dmaven.test.skip=false clean verify
Follow

Get every new post delivered to your Inbox.