On 3 mars 2014, at 16:48, Bengt Rodehav <[email protected]> wrote:

> 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.

Invalidating matching services, also invalidate the selected services (as 
selected is a sorted subset of matching). 
So, something is wrong when invalidating the matching service set.

I suspect something in 
org.apache.felix.ipojo.dependency.impl.ServiceReferenceManager#computeChangesInMatchingServices.

Clement



> 
> /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]
>>> 
>>> 
>> 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to