I call both of them:

  public void invalidateSelectedServices() {
    List<DependencyModel> list = new ArrayList<DependencyModel>();
    synchronized (this) {
      list.addAll(dependencies);
    }

    for (DependencyModel dep : list) {
      if (isMine(dep)) {
        System.out.println("Invalidating matching...");
        dep.invalidateMatchingServices();
        System.out.println("Invalidating selected...");
        dep.invalidateSelectedServices();
        System.out.println("Done invalidating");
      }
    }
  }

  @Override
  synchronized public void configurationChanged(ComponentInstance theArg0,
Map<String, Object> theArg1) {
    System.out.println("configurationChanged invalidating...");
    invalidateSelectedServices();
  }

I think I used to only call invalidateSelectedServices() but then I had the
opposite problem. Since the accept() method wasn't called, the intercepted
property was not set to true. Also, if I only call
invalidateMatchingServices(), the service references are not recalculated.
It is important that both my accept() method and my getServiceReferences()
method are called.

Sounds like this might be an issue now that you mention it. How are the
invalidateXYZ() methods supposed to work?

/Bengt


2014-03-03 16:19 GMT+01:00 Clement Escoffier <[email protected]>:

>
> On 3 mars 2014, at 16:09, Bengt Rodehav <[email protected]> wrote:
>
> > I now added logging to the following methods:
> >
> > - onServiceArrival
> > - onServiceDeparture
> > - onServiceModified
> >
> > I tried starting both with a clean start and then without clean. I got
> the
> > following results:
> >
> > *bin\karaf.bat clean*
> > accept: intercepted
> > onServiceArrival: 1 matching references
> > getServiceReferences
> > accept: intercepted
> >
> > *bin\karaf.bat*
> > accept: intercepted
> > configurationChanged invalidating...
> > Invalidating matching...
> > accept: intercepted
> > Invalidating selected...
> > Done invalidating
> > Validated
> > getServiceReferences
> > Invalidated
> >
> > As you can see the instance never becomes valid on a clean start. Then
> > again, no configuration changes are detected on a clean start. It seems
> to
> > be when I detect a configuration change and manually invalidate the
> > dependencies that the problem appears.
> >
> > Does this give you any clue?
>
> Which method are you calling ? invalidateMatchingServices, or
> invalidateSelectedServices(), anyway it narrows the location of the bug to
> a small amount of code:
>
> public void invalidateMatchingServices() {
>         ChangeSet changeset;
>         try {
>             m_dependency.acquireWriteLockIfNotHeld();
>             m_matchingReferences.clear();
>             changeset = computeChangesInMatchingServices();
>         } finally {
>             m_dependency.releaseWriteLockIfHeld();
>         }
>         m_dependency.onChange(changeset);
>     }
>
>     public void invalidateSelectedServices() {
>         ChangeSet changeset;
>         try {
>             m_dependency.acquireWriteLockIfNotHeld();
>             ServiceReference oldBest = getFirstService();
>             List<ServiceReference> beforeRanking = getSelectedServices();
>             m_selectedReferences.clear();
>             final List<ServiceReference> allServices =
> getMatchingServices();
>             List<ServiceReference> references = Collections.emptyList();
>             if (!allServices.isEmpty()) {
>                 references =
> m_rankingInterceptor.getServiceReferences(m_dependency, allServices);
>             }
>             RankingResult result = computeDifferences(beforeRanking,
> references);
>             m_selectedReferences = result.selected;
>             changeset = new ChangeSet(getSelectedServices(),
> result.departures, result.arrivals, oldBest,
>                     getFirstService(), null, null);
>         } finally {
>             m_dependency.releaseWriteLockIfHeld();
>         }
>
>         m_dependency.onChange(changeset);
>     }
>
> >
> > /Bengt
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > 2014-03-03 15:53 GMT+01:00 Bengt Rodehav <[email protected]>:
> >
> >> OK - I now understand what you mean. It seems that the design is
> supposed
> >> to do what I expected then. We think alike :-)
> >>
> >> I'll add some more tracing as you suggested and then get back to you.
> >>
> >> /Bengt
> >>
> >>
> >> 2014-03-03 15:46 GMT+01:00 Clement Escoffier <
> [email protected]>
> >> :
> >>
> >>
> >>> On 3 mars 2014, at 15:18, Bengt Rodehav <[email protected]> wrote:
> >>>
> >>>> Hi Clement,
> >>>>
> >>>> Yes, I use the filter to make sure that the instance does not become
> >>> valid
> >>>> until it has been intercepted - that part seems to work. However, in
> my
> >>>> case, the instance become valid AFTER my accept() method has been
> called
> >>>> but BEFORE my getServiceReferences() method has been called. This is
> >>>> causing my problems.
> >>>>
> >>>> I'm a little curious regarding your wording:
> >>>>
> >>>> "A (mandatory) dependency becomes valid only if the selected service
> >>> set is
> >>>> not empty. In other words, all your interceptors should have been
> called
> >>>> before deciding to set the dependency state to valid."
> >>>>
> >>>> I don't see how the first sentence has anything to do with the second
> >>>> sentence.
> >>>
> >>> This is how iPOJO resolves services. It first considers the services
> from
> >>> the service registry (called base service set). This set is processed
> by
> >>> tracking interceptor (such as LDAP filter...) to get a matching
> service set.
> >>> Then, a ranking interceptor is called to sort the set, and to get the
> >>> selected service set. A mandatory service dependency cannot be valid if
> >>> this last set is empty (in theory). That means that both accept and
> >>> getServiceReferences should have been called to determine whether or
> not
> >>> the dependency is valid. The accept method is called to build the
> matching
> >>> service set, while getServiceReferences is called to retrieve the
> selected
> >>> service set.
> >>>
> >>>>
> >>>> I have a dependency declared as follows:
> >>>>
> >>>> @Requires(optional = false, id = "extenders", filter =
> >>>> "(intercepted=true)")
> >>>> private IRouteExtender[] mExtenders;
> >>>>
> >>>> Thus it is mandatory. Also, there are services of type IRouteExtender
> >>>> registered so that part is resolved. But until the accept() method has
> >>> been
> >>>> called the "(intercepted=true)" part is not satisfied. When my
> accept()
> >>>> method has been called the "(intercepted=true)" part becomes satisfied
> >>> and
> >>>> my instance becomes valid right away instead of waiting for the result
> >>> of
> >>>> the getServiceReferences() method. This is the problem because in my
> >>>> getServiceReferences() method I evalutate the matching dependencies
> (by
> >>>> looking at a property) and determine that they are not valid. I
> >>> therefore
> >>>> return an empty set of matching service references and the instance
> now
> >>>> becomes invalid.
> >>>>
> >>>> I do not think it should be possible to validate an instance "in the
> >>> midst
> >>>> of intercepting" as is the case for me. I must be completely done
> >>>> intercepting first.
> >>>
> >>> That should not be the case. Definitely a bug.... The dependency state
> >>> should not be re-evaluated before having notified the ranking
> interceptor.
> >>>
> >>> So far, you are implementing only getServiceReferences, can you
> implement
> >>> and add traces in onServiceArrival ?
> >>>
> >>> Clement
> >>>
> >>>
> >>>
> >>>>
> >>>> /Bengt
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> 2014-03-03 13:51 GMT+01:00 Clement Escoffier <
> >>> [email protected]>:
> >>>>
> >>>>> Hi,
> >>>>>
> >>>>> On 3 mars 2014, at 13:14, Bengt Rodehav <[email protected]> wrote:
> >>>>>
> >>>>>> Hello again Clement!
> >>>>>>
> >>>>>> Skiing trip is now over - time to get back to the interceptors...
> >>>>>>
> >>>>>> Regarding your questions in the last post: Yes, I only add a
> property
> >>> on
> >>>>>> the chosen service reference (intercepted is set to true), I do not
> >>>>> change
> >>>>>> the filter.
> >>>>>>
> >>>>>> I have tested the theory regarding config admin / file install and
> it
> >>> is
> >>>>>> not the problem.
> >>>>>>
> >>>>>> It seems to me that there is no guarantee that both accept() and the
> >>>>>> getServiceReferences() are both called before an instance becomes
> >>> valid.
> >>>>> I
> >>>>>> haven't looked at the source code in detail yet but is the design
> such
> >>>>> that
> >>>>>> this is not supposed to be possible or am I requesting a new
> feature?
> >>> In
> >>>>>> other words, have I found a bug or not?
> >>>>>>
> >>>>>> Ideally I think it should work as follows:
> >>>>>>
> >>>>>> - When in "interceptor mode" the state of the instance should not
> >>> change
> >>>>>> until all the interceptors (and all callbacks of the interceptors)
> >>> have
> >>>>>> taken effect.
> >>>>>>
> >>>>>> - Initially then instance should not become valid until all the
> >>>>>> interceptors (and all callbacks of the interceptors) have taken
> >>> effect.
> >>>>>>
> >>>>>> With "interceptor mode" I mean that something has triggered iPojo to
> >>>>> begin
> >>>>>> calling the registered interceptors.
> >>>>>>
> >>>>>> Not sure if this is in accordance with your design. How is it
> >>> supposed to
> >>>>>> work?
> >>>>>
> >>>>>
> >>>>> It might be a bug and a new feature.
> >>>>>
> >>>>> I designed interceptors to be highly dynamic, so can come and leave
> at
> >>>>> anytime, and without having the components aware of them. That's why
> >>>>> service dependencies do not know which interceptors handle them.
> >>>>> Unfortunately, this design has some trade-off / drawbacks. If your
> >>> instance
> >>>>> starts before the interceptors, it might be valid for a little amount
> >>> of
> >>>>> time, until the interceptors handle the dependency. However in your
> >>> case
> >>>>> you have a filter on the dependency that should avoid this case.
> >>>>>
> >>>>> If you still have this filter, it is definitely a bug.  A (mandatory)
> >>>>> dependency becomes valid only if the selected service set is not
> >>> empty. In
> >>>>> other words, all your interceptors should have been called before
> >>> deciding
> >>>>> to set the dependency state to valid.
> >>>>>
> >>>>> About the feature, I start thinking that the independence between the
> >>>>> interceptor and the dependencies may be problematic. For instance,
> I've
> >>>>> another use case where they implement a new handler (an extension of
> >>> the
> >>>>> dependency handler) to ensure the availability of one specific
> >>> interceptor.
> >>>>> The dependency is invalid until the interceptor arrives.
> >>>>>
> >>>>> Clement
> >>>>>
> >>>>>>
> >>>>>> /Bengt
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> 2014-02-24 8:17 GMT+01:00 Clement Escoffier <
> >>> [email protected]
> >>>>>> :
> >>>>>>
> >>>>>>>
> >>>>>>> On 21 févr. 2014, at 14:15, Bengt Rodehav <[email protected]>
> wrote:
> >>>>>>>
> >>>>>>>> Hello Clement,
> >>>>>>>>
> >>>>>>>> Some comments inline below.
> >>>>>>>>
> >>>>>>>> /Bengt
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> 2014-02-21 12:53 GMT+01:00 Clement Escoffier <
> >>>>>>> [email protected]>:
> >>>>>>>>
> >>>>>>>>> Hi,
> >>>>>>>>>
> >>>>>>>>> On 20 févr. 2014, at 13:22, Bengt Rodehav <[email protected]>
> >>> wrote:
> >>>>>>>>>
> >>>>>>>>>> This is a follow up on another discussion I had with Clement on
> >>> this
> >>>>>>>>>> mailing list:
> >>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>
> >>>>>>>
> >>>>>
> >>>
> http://apache-felix.18485.x6.nabble.com/Using-iPojo-interceptors-tt5006168.html#a5006276
> >>>>>>>>>>
> >>>>>>>>>> I'm now trying to get the interceptor solution into production.
> >>>>>>>>>>
> >>>>>>>>>> Remember that I have to invalidate my instances when their
> >>>>>>> configuration
> >>>>>>>>> is
> >>>>>>>>>> changed. This is because I need to re-evalutate the dependencies
> >>> for
> >>>>>>> the
> >>>>>>>>>> instance.
> >>>>>>>>>>
> >>>>>>>>>> Originally, I only called the invalidateSelectedServices()
> method
> >>> on
> >>>>>>> the
> >>>>>>>>>> DependencyModel. This worked mostly but not when starting a
> fresh
> >>>>>>>>> container
> >>>>>>>>>> (I use Karaf and start it with "bin\karaf.bat clean"). My
> instance
> >>>>> then
> >>>>>>>>>> first becomes valid but then becomes invalid. I think this is
> >>> because
> >>>>>>> of
> >>>>>>>>>> the ordering. The accept() method had not been called prior to
> >>>>>>>>>> the getServiceReferences() method. The dependency is therefore
> not
> >>>>> set
> >>>>>>> to
> >>>>>>>>>> "intercepted=true" which makes it invalid.
> >>>>>>>>>
> >>>>>>>>> the filter is updated by the interceptor. (just want to be sure I
> >>>>>>>>> understand). In that case, if the interceptor arrives after the
> >>>>> instance
> >>>>>>>>> creation, the filter will be set when the interceptor arrives.
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> Yes, my interceptor sets intercepted to true on the dependency
> which
> >>>>>>> makes
> >>>>>>>> sure that the filter match.
> >>>>>>>
> >>>>>>> So the filter is not modified by the interceptor, it just add a new
> >>>>>>> property on the chosen service reference to match the filter.
> >>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> Replacing the call to  invalidateSelectedServices() with a call
> to
> >>>>>>>>>> invalidateMatchingServices() seems to do the trick. However,
> >>> there is
> >>>>>>> one
> >>>>>>>>>> small glitch that I would like to fix.
> >>>>>>>>>>
> >>>>>>>>>> If I have a configuration that should not be valid (e g I
> >>> specified
> >>>>> an
> >>>>>>>>>> extender id that is not present) the instance should never be
> >>> valid.
> >>>>>>> But,
> >>>>>>>>>> when starting Karaf (both with "bin\karaf.bat" and
> "bin\karaf.bat
> >>>>>>>>> clean"),
> >>>>>>>>>> the instance becomes valid before it becomes invalid. It does
> end
> >>> up
> >>>>> in
> >>>>>>>>> the
> >>>>>>>>>> right state (invalid in this case) but for a short period of
> time
> >>> it
> >>>>> is
> >>>>>>>>>> valid which will cause a lot of things to happen in my code that
> >>> then
> >>>>>>>>> must
> >>>>>>>>>> be reversed when it becomes invalid.
> >>>>>>>>>>
> >>>>>>>>>> I logged the sequence of events and it seems that the accept()
> >>> method
> >>>>>>> is
> >>>>>>>>>> called first. I will then set "intercepted=true". This
> immediately
> >>>>>>> makes
> >>>>>>>>>> the instance valid. Shortly thereafter getServiceReferences() is
> >>>>>>> called.
> >>>>>>>>> I
> >>>>>>>>>> will then re-calculate the dependency requirements and when I
> >>> later
> >>>>>>>>>> invalidate the dependencies the instance will become valid.
> >>>>>>>>>>
> >>>>>>>>>> So, there is a short time frame where the instance is valid
> >>> although
> >>>>> it
> >>>>>>>>>> shouldn't be. How can I fix that?
> >>>>>>>>>
> >>>>>>>>> This looks like a bug, as the dependency can be valid only if the
> >>> set
> >>>>> of
> >>>>>>>>> selected services is not empty. From what you say, it looks like
> >>> the
> >>>>>>>>> dependency is valid because the set of matching services is not
> >>> empty.
> >>>>>>>>>
> >>>>>>>>
> >>>>>>>> Is there anything I can do to investigate this? Is it possible for
> >>> you
> >>>>> to
> >>>>>>>> take a look if there is indeed a "gap" where this can happen?
> >>>>>>>
> >>>>>>> My first guess would be in the ServiceReferenceManager coordinating
> >>> the
> >>>>>>> interceptors.
> >>>>>>>
> >>>>>>>>
> >>>>>>>> I think that things are a little complicated since I also listen
> on
> >>>>>>>> configuration changes. I need to recalculate the matching services
> >>> when
> >>>>>>> the
> >>>>>>>> configuration of the intercepted instance changes. When starting
> the
> >>>>>>>> container (Karaf), I get more than one configuration change and
> thus
> >>>>> the
> >>>>>>>> dependencies are invalidated more than once. What if the sequence
> >>> were:
> >>>>>>>>
> >>>>>>>> 1. Configuration change causing the dependencies to become
> >>> invalidated
> >>>>>>>> 2. Accept. Will set intercepted to true
> >>>>>>>> 3. getServiceReferences which will calculate the required
> >>> dependencies
> >>>>>>>> 4. Configuration change again causing the dependencies to become
> >>>>>>> invalidated
> >>>>>>>> 5. Accept. Will set intercepted to true
> >>>>>>>> 6. getServiceReferences which will calculate the required
> >>> dependencies
> >>>>>>>>
> >>>>>>>> Not sure if there is any point in which an instance could become
> >>> valid
> >>>>>>> when
> >>>>>>>> it shouldn't.
> >>>>>>>>
> >>>>>>>> I will also try to see if the problem could be the configuration
> >>>>> admin. I
> >>>>>>>> use file install for my configuration. I have a feeling that the
> >>> first
> >>>>>>>> configuration being pushed is a default configuration and not the
> >>> one
> >>>>>>> from
> >>>>>>>> the configuration file. Then that might explain it.
> >>>>>>>>
> >>>>>>>
> >>>>>>> Oh, that's an interesting hint. That's definitely possible.
> >>>>>>>
> >>>>>>> Enjoy your vacations, mine are over....
> >>>>>>>
> >>>>>>>
> >>>>>>> Regards,
> >>>>>>>
> >>>>>>> Clement
> >>>>>>>
> >>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> From my point of view this is similar to a transaction. I do not
> >>> want
> >>>>>>> the
> >>>>>>>>>> instance to become valid before I have done all my
> "intercepting"
> >>>>> which
> >>>>>>>>> is
> >>>>>>>>>> after BOTH the accept() method AND the getServiceReferences()
> >>> method
> >>>>>>> have
> >>>>>>>>>> been called.
> >>>>>>>>>
> >>>>>>>>> In theory, it is how it should work...
> >>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> BTW I also noted that the "dependencies" member in
> >>>>>>>>>> the DefaultDependencyInterceptor class (I extend the
> >>>>>>>>>> DefaultServiceRankingInterceptor class) seems to contain
> >>> duplicates
> >>>>> of
> >>>>>>> my
> >>>>>>>>>> dependency. The same DependencyModel instance occurs twice in
> the
> >>>>> List.
> >>>>>>>>>> Seems like a bug to me. Perhaps the List should be a Set?
> >>>>>>>>>
> >>>>>>>>> Definitely, could you open an issue ?
> >>>>>>>>>
> >>>>>>>>> Clement
> >>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>> /Bengt
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>> ---------------------------------------------------------------------
> >>>>>>>>> To unsubscribe, e-mail: [email protected]
> >>>>>>>>> For additional commands, e-mail: [email protected]
> >>>>>>>
> >>>>>>>
> >>>>>
> >>>>>
> >>>>> ---------------------------------------------------------------------
> >>>>> To unsubscribe, e-mail: [email protected]
> >>>>> For additional commands, e-mail: [email protected]
> >>>>>
> >>>>>
> >>>
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: [email protected]
> >>> For additional commands, e-mail: [email protected]
> >>>
> >>>
> >>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>

Reply via email to