*One more detail at the bottom:*

On Mon, Dec 13, 2010 at 5:11 PM, David Orme
<[email protected]>wrote:

> Hi Tomas,
>
> On Fri, Dec 10, 2010 at 5:58 PM, Thomas Hallgren <[email protected]> wrote:
>
>>  The traverse query was written with the intention to replace the slicer
>> but we never got around to actually do that in the 3.6 time frame. As it
>> stands today, it's not a clean cut replacement. The slicer (permissive or
>> non-permissive) will give you specific control over the query that is
>> applicable for a couple of use-cases that is utilized by the PDE target
>> platform provisioning system. One is for instance to guess whether a
>> requirement stems from a PDE-feature 'include' or a PDE-feature 'requires'
>> by looking at the version range (exact or not) in the requirement.
>>
>
> Thanks for the clarification.
>
>
>> The traverse query is generic and not capable of performing special
>> considerations like that. It is however proven to be both faster and more
>> memory conservative than the slicer so I guess the answer to your question
>> all depends on your requirements. It would be easier to give a good answer
>> if we knew more about what it is you want to accomplish.
>>
>
> Sure; here's what's up* (short version)*:
>
> We have an headless installer/updater built on top of Update Manager that
> I'm trying to move to P2.  Basically right now I'm spiking various use-cases
> in P2 with a view to forming an opinion about the best way to reimplement
> this API on top of P2.
>
> But that's not all.  At EclipseCon, we contributed our headless installer
> API to E4 with a view to make it easy for others to build RCP applications
> like we have:
>
> (a) When an application starts up, it checks for updates and automatically
> downloads/installs them.
>
> (b) Alternatively, when a user logs in, the application contacts a
> provisioning server and obtains a list of Features/Versions that the user is
> permitted to use.  We then call Update Manager and install/update ONLY those
> Features/Versions and appropriate dependencies.
>
> So we'd love to have feedback/input from the community.
>
> *Detail:*
>
> We've got (a) above tackled using P2.  We're struggling a bit with the API
> to implement (b).
>
> The API that implements (b) is:
>
> public boolean update(URL[] updateSiteURLs, File downloadRootDir, 
> Set<FeatureVersionedIdentifier> featuresRequested) throws InstallError
>
>
> In P2 terms, *updateSiteURLs *wind up being consolidated into a
> compoundQueryable.
>
> I'm not sure what P2 terms are yet for *downloadRootDir*, but I'm guessing
> that this has something to do with P2 Profiles?  In Update Manager, this
> specified a root directory where we would create your install site(s).  The
> purpose is to enable installations on Citrix or *nixes where the
> installation directory might not be writable; this we have to support
> putting updates somewhere else.
>
> *featuresRequested *is the set of Features that the current user is
> allowed to use.  It obviously must be a subset of the features on *
> updateSiteURLs*.
>
> [[A *FeatureVersionedIdentifier *simply is a (String, String) pair where
> the first String is the Feature ID and the second is either the exact
> version, a version number without the qualifier, or "0.0.0" to specify the
> latest version.  (*IFeatureReference *doesn't implement equals/hashCode,
> so we needed something that would be usable in collections.  Plus we wanted
> to be independent of Update Manager so we could later move to P2.)  This
> class is very similar to an *InstallableUnitDescription*, but just for
> Features; maybe there's another even closer match in P2?]]
>
> *featuresRequested *is basically our query API.
>
> More or less current code can be found at:
>
>
> http://git.eclipse.org/c/e4/org.eclipse.e4.installer.git/tree/bundles/org.eclipse.e4.enterprise.installer/src/org/eclipse/e4/enterprise/installer/BundleUpdater.java
>
> *Current questions:*
>
> My (spiked) update method looks like the following; (important lines
> bolded):
>
>
> //Loading repos
> Collection<IMetadataRepository> metadataReposList = new
> LinkedList<IMetadataRepository>();
> metadataReposList.add(metadataManager.loadRepository(new URI(P2SITE),
> monitor));
> metadataReposList.add(metadataManager.loadRepository(new
> URI(SECOND_P2SITE), monitor));
> metadataReposList.add(metadataManager.loadRepository(new URI(THIRD_P2SITE),
> monitor));
>
> artifactManager.loadRepository(new URI(P2SITE), monitor);
> artifactManager.loadRepository(new URI(SECOND_P2SITE), monitor);
> artifactManager.loadRepository(new URI(THIRD_P2SITE), monitor);
>
> //Querying
> final String traverseQuery = "$0.traverse(parent |
> parent.requirements.collect(rc | select(iu |iu ~= rc)).flatten())";
>
> IQueryable<IInstallableUnit> allMetadataRepos =
> QueryUtil.compoundQueryable(metadataReposList);
>
> Set<IInstallableUnit> toInstallOrUpdate = null;
> ArrayList<IInstallableUnit> ius = getIUsToInstall();
>
> try {
> *    if (ius.size() > 0) {
>         toInstallOrUpdate = allMetadataRepos.query(
>             QueryUtil.createQuery(traverseQuery, ius),
> monitor).toUnmodifiableSet();
>     } else {
>
>         toInstallOrUpdate = allMetadataRepos.query(
>             QueryUtil.createIUAnyQuery(), monitor).toUnmodifiableSet();
>     }
> *} catch (Throwable t) {
>     IStatus result = error(t.getMessage(), t);
>     log(result);
>     return result;
> }
>
> // Perform the install
> InstallOperation installOperation = new InstallOperation(session,
> toInstallOrUpdate);
> resolveJob = installOperation.getResolveJob(monitor);
> IStatus installStatus = syncRunJob(monitor, resolveJob);
> if (null == resolveJob) {
>     return log(error("Unexpected: installOperation#getResolveJob returned
> null!", new NullPointerException()));
> }
> log(info("Result of resolving install opearations: " +
> installStatus.getMessage()));
> if (installStatus.isOK()) {
>     log(info("Installing..."));
>     ProvisioningJob provisioningJob =
> installOperation.getProvisioningJob(monitor);
>     if (null == provisioningJob) {
>         return log(error("Unexpected: installOperation#getProvisioningJob
> returned null!", new NullPointerException()));
>     }
>     installStatus = syncRunJob(monitor, provisioningJob);
>     log(info("Install result: " + installStatus.getMessage()));
> } else {
>     log(info("Install status returned !ok: " +
> installStatus.getMessage()));
> }
>
>
> The key part is the "if" clause I bolded above.
>
> If there are no IUs in the list, we (in the spike) install everything, just
> to prove that the rest of the code works right.  When I go through that code
> path, everything works fine.
>
> However, when I explicitly specify the .feature.group(s) to install, then
> the IUs I get back from the query are exactly the .feature.group(s) I used
> as input, and nothing else.  No plugins, no included/dependent features,
> nothing.  Naturally, this fails.
>
> I'm not sure where to go next.
>
> In your opinion, is this the right approach or should I be using the
> slicer?  (It seems fine to me for our API, but I might be missing
> something.)
>
> I'll try to get a small example together that I can upload somewhere.
>
>
Here's the code I use to create an IU:

private IInstallableUnit newIU(String id, String versionString) {
    InstallableUnitDescription iuDesc = new
MetadataFactory.InstallableUnitDescription();
    iuDesc.setId(id);
    Version version = Version.create(versionString);
    iuDesc.setVersion(version);
    ArrayList<IProvidedCapability> capabilities = new
ArrayList<IProvidedCapability>();
    capabilities.add(MetadataFactory.createProvidedCapability(id, id,
version));
    iuDesc.addProvidedCapabilities(capabilities);
    return MetadataFactory.createInstallableUnit(iuDesc);
}


Thanks again,

Dave
_______________________________________________
p2-dev mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/p2-dev

Reply via email to