I now tried to call only one of those methods with the following result:

ONLY SELECTED

bin\karaf.bat clean
-------------------
accept: intercepted
onServiceArrival: 1 matching references
getServiceReferences
accept: intercepted

bin\karaf.bat
-------------
accept: intercepted
configurationChanged invalidating...
Invalidating selected...
Done invalidating
Validated
getServiceReferences
Invalidated


ONLY MATCHING

bin\karaf.bat clean
-------------------
accept: intercepted
onServiceArrival: 1 matching references
getServiceReferences

bin\karaf.bat
-------------
karaf@root> accept: intercepted
configurationChanged invalidating...
Invalidating matching...
accept: intercepted
Done invalidating
Validated
getServiceReferences
Invalidated

It seems to give the same result as calling both of them.

/Bengt


2014-03-03 16:36 GMT+01:00 Bengt Rodehav <[email protected]>:

> 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