7 Replies Latest reply on Aug 5, 2010 9:54 AM by thomas.diesler

    Adding a revision number to the XModule API

    bosschaert

      To support multiple revisions of the same bundle and to make the resolver work with this, we could add a revision number to the XModule API and the XModuleBuilder factory methods. This would mean that to the resolver multiple revisions of the same module (=bundle) are viewed as completely independent modules.

       

      The revision number can also be used for the case where an existing bundle needs to be rewired because its dependencies have changed. In that case you simply create a new revision of that bundle based on the original content. When the bundle is resolved, it will automatically get new wires from the resolver.

       

      I've implemented it here: http://github.com/jbosgi/jbosgi-resolver/tree/update

        • 1. Re: Adding a revision number to the XModule API
          thomas.diesler

          Lets look at the larger picture as well

           

          * The framework maintains a set of bundles that can come and go at any time

          * bundle resolution is triggered by bundle.start() or a class loading attempt

          * The osgi resolver should work on a non-changing set of modules to find the wirings between them

          * The resulting wirings must be applied to the set of framework bundles in an atomic operation

           

          Felix talks of the ResolverState and the Resolver. The ResolverState is a snapshot and hence non-changing set of modules while the Resolver itself is stateless. Although there is an issue with fragments in the current felix resolver impl - this is the theory.

           

          Applied to our MSC framework it means that we first need to decide whether the XResolver also maintains the resolver state, which it curretly does and is unlike the Felix resolver (i.e. you can add/remove XModules) and the resolve operation is constraint to work on XModules you have previously added.

           

          If we keep it this way, the ResolverPlugin should be able to manage multiple XResolver instances concurrently. So adding a bundle to the framework does not interfere with a running resolve operation. The callback could still be used to collect resolver results, the framework bundles must be updated more intelligently/atomically. The lock operations could be removed from the callback.

           

          If we choose to change the XResolver API to become stateless, the ResolverPlugin must create the XModule snapshots and effectivly maintain multiple such snapshots concurrently. Resolver state management is the responsibiliy of the client (i.e. the ResolverPlugin)

           

          In any case, the XModule which is associated with a framework bundle should never be the one that is given to the resolver. Instead when the resolver is done the wirings must be applied to the bundle associated XModules in one go (i.e. atomically)

           

          So it seems that the XModule that the resolver operates on during the resolve operation is short lived and should only exist for the duration of the resolve plus processing of its result set. The BundleRevision does not seem to be needed in addition to the BundleId. Actually, I believe that the resolver should always works on specific BundleRevisions and never on the InternalBundle. If I remember correctly we said we would reuse the ModuleIdentifier as the BundleRevision identity. The resolver API should however not be coupled to org.jboss.modules

          • 2. Re: Adding a revision number to the XModule API
            thomas.diesler

            IMHO the XResolver could stay to be the maintainer of the state, which would allow for incremental resolve operations. It could also have two additional methods

             

            * refreshModule(XModule)

            * refreshModules(Set<XModule>)

             

            The XResolverCallback could be chaged to the more general case

             

            * updateWiring(XModule, XWire[])

             

            whereas the xwire array can be null.

             

            When you call refreshModule(XModule) the XResolver would compute the set of modules that need "unwiring" and call 'updateWiring' for each XModule in the transitive closure. If you call refreshModules(null) you would get a callback for every registered module in that XResolver instance.

            • 3. Re: Adding a revision number to the XModule API
              bosschaert

              I have no problems with keeping XResolver stateful.

              Thomas Diesler wrote:

               

              I believe that the resolver should always works on specific BundleRevisions and never on the InternalBundle. If I remember correctly we said we would reuse the ModuleIdentifier as the BundleRevision identity. The resolver API should however not be coupled to org.jboss.modules

               

              Zooming in on the actual issue, as you say, the resolver only works on bundle revisions. There is at most 1 XModule instance per BundleRevision, so in theory I agree that it would be possible to keep the revision out of the XModule.

              However, in ModuleManager.createModuleSpec() there is a quite a bit of logic that uses ModuleManager.getModuleIdentifier(XModule) without having the associated BundleRevision. I guess it might be possible to obtain the associated BundleRevision and its revision from the XModule by getting a BundleRevision attachment from it, but that would be rather awkward. Storing the revision inside XModule is a simple way to retrieve it again.

              • 4. Re: Adding a revision number to the XModule API
                bosschaert

                Thomas Diesler wrote:

                 

                IMHO the XResolver could stay to be the maintainer of the state, which would allow for incremental resolve operations. It could also have two additional methods

                 

                * refreshModule(XModule)

                * refreshModules(Set<XModule>)

                 

                The XResolverCallback could be chaged to the more general case

                 

                * updateWiring(XModule, XWire[])

                 

                whereas the xwire array can be null.

                 

                When you call refreshModule(XModule) the XResolver would compute the set of modules that need "unwiring" and call 'updateWiring' for each XModule in the transitive closure. If you call refreshModules(null) you would get a callback for every registered module in that XResolver instance.

                I actually started off this way, but in the end I don't need all this to achieve what I currently do with update/refresh. Because every time a bundle is updated or needs to be rewired (rewiring can be seen as a special type of update where the bundle difinition hasn't changed) a new revision is created and associated with this new revision is a new XModule. So the XModule instances themselves are actually not refreshed nor rewired.

                • 5. Re: Adding a revision number to the XModule API
                  bosschaert

                  Actually, I just tried to implement this by putting the BundleRevision to the XModule as an attachment. It's not too bad and it probably makes sense to have this relation available.

                  • 6. Re: Adding a revision number to the XModule API
                    thomas.diesler

                    Agreed. I was saying

                     

                    The BundleRevision does not seem to be needed in addition to the  BundleId

                     

                    So an XModule would bi-directionally correlate to a BundleRevision.

                     

                    Whats your take on the changes to the ResolverPlugin and XResolver I suggested above?

                    • 7. Re: Adding a revision number to the XModule API
                      thomas.diesler

                      If the identity of an XModule is the BundleRevision identifier, XModule.getModuleId() needs to be in sync with this notion. From the BundleRevision you would be able to get to the Bundle.