Immutable OpenBitSet?

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Immutable OpenBitSet?

Nader, John P
Hello,

We have an application that relies heavily on caching OpenBitSets for reuse across multiple threads, and therefore multiple threads.  I am looking into ways for making this both efficient and thread safe.  In Java, the Immutable pattern is the most efficient way to make a cached object thread safe, because it does not require synchronization overhead.  Unfortunately, this would require an implementation of OpenBitSet with the 'bits' and 'wlen' fields declared as final, and all mutator methods throwing unsupported.  I can certainly extend the class to override the methods, but the fields cannot be overridden as final.

Are there any suggestions of the forum?  Possibly other Lucene classes to solve this problem?  Or other solutions?

I'm just looking for ideas.  Thanks.

-John
Reply | Threaded
Open this post in threaded view
|

Re: Immutable OpenBitSet?

Michael McCandless-2
This would be very useful to have, but I don't think Lucene has it
now.  Maybe Solr does?  If not, please submit a patch :)

Or, maybe try http://sna-projects.com/kamikaze?  I think the focus
there is compressed docID sets (in RAM), so I'm not sure you'll find
something there... but, maybe?

Mike

http://blog.mikemccandless.com

On Wed, Apr 27, 2011 at 2:28 PM, Nader, John P <[hidden email]> wrote:

> Hello,
>
> We have an application that relies heavily on caching OpenBitSets for reuse across multiple threads, and therefore multiple threads.  I am looking into ways for making this both efficient and thread safe.  In Java, the Immutable pattern is the most efficient way to make a cached object thread safe, because it does not require synchronization overhead.  Unfortunately, this would require an implementation of OpenBitSet with the 'bits' and 'wlen' fields declared as final, and all mutator methods throwing unsupported.  I can certainly extend the class to override the methods, but the fields cannot be overridden as final.
>
> Are there any suggestions of the forum?  Possibly other Lucene classes to solve this problem?  Or other solutions?
>
> I'm just looking for ideas.  Thanks.
>
> -John
>

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

Reply | Threaded
Open this post in threaded view
|

Re: Immutable OpenBitSet?

Federico Fissore
In reply to this post by Nader, John P
Nader, John P, il 27/04/2011 20:28, ha scritto:
> Hello,
>
> We have an application that relies heavily on caching OpenBitSets for reuse across multiple threads, and therefore multiple threads.
[...]


You don't need synchronization if you just read from an openbitset. And
if you need to modify it, you can achieve thread safeness even with
thread confinement.

BTW (shameless plug) if you are going to operate on large sets of
bitsets, you should probably take a look at
https://github.com/ffissore/Parallel-Bitset-Operations
we are integrating it into some of our searchers

HTH

federico

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

Reply | Threaded
Open this post in threaded view
|

RE: Immutable OpenBitSet?

Nader, John P
Thanks.  Your project looks interesting.  We've got some duplicate home-grown stuff here that is similar.

As far as thread-safety, if one thread initializes an OpenBitSet's by setting one or bits and then hands that off to another thread, the other thread may see partial results.  The long[] is not protected by read/write synchronization, nor does it get any of the guarantees of final.  This is problematic for caching bit sets.

My idea for an optimal and guaranteed thread-safe implementation would be a class nearly identical to OpenBitSet except:
 - Only implements read operation (gets, tests, compares, etc.)
 - Is constructed from an already initialized long[] or another OpenBitSet.
 - declares its reference to bits and wlen as final.

There are a few problems with implementing equals, since that directly accesses the non-final field on OpenBitSet.


-----Original Message-----
From: Federico Fissore [mailto:[hidden email]]
Sent: Wednesday, April 27, 2011 5:12 PM
To: [hidden email]
Subject: Re: Immutable OpenBitSet?

Nader, John P, il 27/04/2011 20:28, ha scritto:
> Hello,
>
> We have an application that relies heavily on caching OpenBitSets for reuse across multiple threads, and therefore multiple threads.
[...]


You don't need synchronization if you just read from an openbitset. And
if you need to modify it, you can achieve thread safeness even with
thread confinement.

BTW (shameless plug) if you are going to operate on large sets of
bitsets, you should probably take a look at
https://github.com/ffissore/Parallel-Bitset-Operations
we are integrating it into some of our searchers

HTH

federico

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


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

Reply | Threaded
Open this post in threaded view
|

RE: Immutable OpenBitSet?

Uwe Schindler
There are solutions to solve the initialization problem. The JVM guarantees
that an object is consistent after the ctor is run, so you can do the
initialization like this (please note the double {{}}, which is an inline
ctor, this is also often seen for unmodifiable HashSets):

final OpenBitSet mybits = new OpenBitSet(size) {{
        fastSet(1); fastSet(2);...
}};

The same is often used for HashSets:

final Set<String> myFinalUnmodifiableSet = Collections.unmodifiableSet(new
HashSet<String>() {{
        add(a); add(b); add(c);...
}});

The only thing we don't have a is a unmodifiable wrapper for OpenBitSet, but
in the above example its only there to prevent modification, but for theread
safety it has no effect (the HashSet contents do not get final by that).

In general you cannot make the bits array final at all (you can make the
reference to it final, but not the contents).
You may also review Michael Busch's talk on last Lucene Revolution / Berlin
Buzzwords on Twitter's Lucene-based Realtime Search, he explains some tricks
to make arrays threadsafe without too much locking.

Uwe

-----
Uwe Schindler
H.-H.-Meier-Allee 63, D-28213 Bremen
http://www.thetaphi.de
eMail: [hidden email]

> -----Original Message-----
> From: Nader, John P [mailto:[hidden email]]
> Sent: Thursday, April 28, 2011 12:24 AM
> To: [hidden email]
> Subject: RE: Immutable OpenBitSet?
>
> Thanks.  Your project looks interesting.  We've got some duplicate home-
> grown stuff here that is similar.
>
> As far as thread-safety, if one thread initializes an OpenBitSet's by
setting
> one or bits and then hands that off to another thread, the other thread
may
> see partial results.  The long[] is not protected by read/write
synchronization,
> nor does it get any of the guarantees of final.  This is problematic for
caching
> bit sets.
>
> My idea for an optimal and guaranteed thread-safe implementation would
> be a class nearly identical to OpenBitSet except:
>  - Only implements read operation (gets, tests, compares, etc.)
>  - Is constructed from an already initialized long[] or another
OpenBitSet.

>  - declares its reference to bits and wlen as final.
>
> There are a few problems with implementing equals, since that directly
> accesses the non-final field on OpenBitSet.
>
>
> -----Original Message-----
> From: Federico Fissore [mailto:[hidden email]]
> Sent: Wednesday, April 27, 2011 5:12 PM
> To: [hidden email]
> Subject: Re: Immutable OpenBitSet?
>
> Nader, John P, il 27/04/2011 20:28, ha scritto:
> > Hello,
> >
> > We have an application that relies heavily on caching OpenBitSets for
reuse
> across multiple threads, and therefore multiple threads.
> [...]
>
>
> You don't need synchronization if you just read from an openbitset. And if
> you need to modify it, you can achieve thread safeness even with thread
> confinement.
>
> BTW (shameless plug) if you are going to operate on large sets of bitsets,
you
> should probably take a look at
https://github.com/ffissore/Parallel-Bitset-

> Operations
> we are integrating it into some of our searchers
>
> HTH
>
> federico
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]



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

Reply | Threaded
Open this post in threaded view
|

Re: Immutable OpenBitSet?

Dawid Weiss-2
There are solutions to solve the initialization problem. The JVM guarantees
> that an object is consistent after the ctor is run, so you can do the
> initialization like this (please note the double {{}}, which is an inline
> ctor, this is also often seen for unmodifiable HashSets):
>
> final OpenBitSet mybits = new OpenBitSet(size) {{
>        fastSet(1); fastSet(2);...
> }};
>

To  complete Uwe's hint: note the object is assigned to a final field -- JVM
guarantees publication safety in correlation with final fields or static
initializer (which in turn result from class loading spec). If you Google
for safe publication you'll find a lot of information about this.

Dawid
Reply | Threaded
Open this post in threaded view
|

Re: Immutable OpenBitSet?

Federico Fissore
In reply to this post by Nader, John P
Nader, John P, il 28/04/2011 00:24, ha scritto:
> Thanks.  Your project looks interesting.  We've got some duplicate home-grown stuff here that is similar.
>
> As far as thread-safety, if one thread initializes an OpenBitSet's by setting one or bits and then hands that off to another thread, the other thread may see partial results.
[...]


I see your point. As Uwe said, you can safe publish an object
initialized by a static initializer.
 From Java Concurrency in Practice, page 52, you read

--
To publish an object safely, both the reference to the object and the
object’s state must be made visible to other threads at the same time. A
properly constructed object can be safely published by:
• Initializing an object reference from a static initializer;
• Storing a reference to it into a volatile field or AtomicReference;
• Storing a reference to it into a final field of a properly constructed
object; or
• Storing a reference to it into a field that is properly guarded by a
lock.
--

The last point means that if your bitset cache is backed by a
synchronized collection, the JVM will guarantee the safe publication
even of a non-thread-safe objects

federico

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

Reply | Threaded
Open this post in threaded view
|

RE: Immutable OpenBitSet?

Uwe Schindler
In general a *newly* created object that was not yet seen by any other
thread is always safe. This is why I said, set all bits in the ctor. This is
easy to understand: Before the ctor returns, the object's contents and all
references like arrays are not seen by any other thread (that's guaranteed).

But in general, this is also true for any factory method: e.g. when
Filter.getDocIdSet() creates an OpenBitSet and returns it, the whole BitSet
is invisible to any other thread before it's "publihsed" by returning from
this method. So after the method returns it first gets visible. Inside the
getDocIdSet method its still private and therefore invisible to any other
thread. So the pattern of Filters creating DocIdSets is perfectly valid (and
works, as you see with CachingWrapperFilter). There is no need to
explicitely make OpenBitSets immutable. The only thing you should ensure is
that you don't modify them - and that the reason behind making it final.

As Federico said before, you should read the famous book about Java
Concurrency:
http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601

Uwe

-----
Uwe Schindler
H.-H.-Meier-Allee 63, D-28213 Bremen
http://www.thetaphi.de
eMail: [hidden email]


> -----Original Message-----
> From: Federico Fissore [mailto:[hidden email]]
> Sent: Thursday, April 28, 2011 9:08 AM
> To: [hidden email]
> Subject: Re: Immutable OpenBitSet?
>
> Nader, John P, il 28/04/2011 00:24, ha scritto:
> > Thanks.  Your project looks interesting.  We've got some duplicate home-
> grown stuff here that is similar.
> >
> > As far as thread-safety, if one thread initializes an OpenBitSet's by
setting
> one or bits and then hands that off to another thread, the other thread
may
> see partial results.
> [...]
>
>
> I see your point. As Uwe said, you can safe publish an object initialized
by a
> static initializer.
>  From Java Concurrency in Practice, page 52, you read
>
> --
> To publish an object safely, both the reference to the object and the
object's
> state must be made visible to other threads at the same time. A properly
> constructed object can be safely published by:
> . Initializing an object reference from a static initializer; . Storing a
reference
> to it into a volatile field or AtomicReference; . Storing a reference to
it into a
> final field of a properly constructed object; or . Storing a reference to
it into a
> field that is properly guarded by a lock.
> --
>
> The last point means that if your bitset cache is backed by a synchronized
> collection, the JVM will guarantee the safe publication even of a
non-thread-
> safe objects
>
> federico
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]



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

Reply | Threaded
Open this post in threaded view
|

Re: Immutable OpenBitSet?

Dawid Weiss-2
> In general a *newly* created object that was not yet seen by any other
> thread is always safe. This is why I said, set all bits in the ctor. This
> is
> easy to understand: Before the ctor returns, the object's contents and all
> references like arrays are not seen by any other thread (that's
> guaranteed).
>

Yes, this is obvious, but simply having a static factory method like this:

public static MyComplexObject create() {
  return new MyComplexObject();
}

does not make the returned object consistent for multithreaded use simply
because nothing has been said about how this object is handed over to other
threads. If it's field-sharing (without volatiles and finals) then the
assigned reference (and whatever content it allocated) may be seen properly
on hardware architectures ensuring memory consistency, but can fail on other
architectures with relaxed caches requiring explicit memory barriers.

Like I said though -- incorrect programs work on most jvms anyway (either
because the hardware fixes the problem or the jvm is not aggressive enough
in the optimizations it could make).

Dawid
Reply | Threaded
Open this post in threaded view
|

Re: Immutable OpenBitSet?

Trejkaz
In reply to this post by Uwe Schindler
On Thu, Apr 28, 2011 at 6:13 PM, Uwe Schindler <[hidden email]> wrote:
> In general a *newly* created object that was not yet seen by any other
> thread is always safe. This is why I said, set all bits in the ctor. This is
> easy to understand: Before the ctor returns, the object's contents and all
> references like arrays are not seen by any other thread (that's guaranteed).

Section 17.5 of the JLS gives the following example:

    class FinalFieldExample {
      final int x;
      int y;
      static FinalFieldExample f;
      public FinalFieldExample() {
        x = 3;
        y = 4;
      }
      static void writer() {
        f = new FinalFieldExample();
      }
      static void reader() {
        if (f != null) {
          int i = f.x; // guaranteed to see 3
          int j = f.y; // could see 0
        }
      }
    }

Essentially, there is no guarantee that the work in the constructor
has been completed when another thread gets a reference to the object.
 To make the guarantee, use the final keyword.

It seems like this contradicts the claim above, but maybe I'm missing something.

TX

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

Reply | Threaded
Open this post in threaded view
|

Re: Immutable OpenBitSet?

Dawid Weiss-2
>      static void writer() {
>        f = new FinalFieldExample();
>      }
>      static void reader() {
>        if (f != null) {
>          int i = f.x; // guaranteed to see 3
>          int j = f.y; // could see 0
>        }
>      }
>    }
>

In this snippet of code there's not even a guarantee that reader() will see
the change to field f... I used to create puzzlers for students around spin
loops that got optimized away by hotspot to never again reference the
(condition) field because the code never mutated it inside the loop. So
something like this:

while (f == null) {}

should get jitted into this:

while (true) {}

D.
Reply | Threaded
Open this post in threaded view
|

RE: Immutable OpenBitSet?

Uwe Schindler
In reply to this post by Trejkaz
This is all not a problem, if the reference to the newly created object is passed e.g. into a synchronized cache (like it is done in CachingWrapperFilter). When entering the synchronized method that adds the reference to the object to the cache (in the filter case it’s the OpenBitSet created shortly before), a memory barrier will make the complete object with all its references published to all.

So:

bs = new OpenBitSet();
bs.fastSet(something);
synchronized (cacheLock) {
        cache.put(rederKey, bs);
}

Is safe as after the synchronized, the memory barrier causes safe publish. This is what also Federico Fissore said.

-----
Uwe Schindler
H.-H.-Meier-Allee 63, D-28213 Bremen
http://www.thetaphi.de
eMail: [hidden email]


> -----Original Message-----
> From: Trejkaz [mailto:[hidden email]]
> Sent: Thursday, April 28, 2011 2:45 PM
> To: [hidden email]
> Subject: Re: Immutable OpenBitSet?
>
> On Thu, Apr 28, 2011 at 6:13 PM, Uwe Schindler <[hidden email]> wrote:
> > In general a *newly* created object that was not yet seen by any other
> > thread is always safe. This is why I said, set all bits in the ctor.
> > This is easy to understand: Before the ctor returns, the object's
> > contents and all references like arrays are not seen by any other thread
> (that's guaranteed).
>
> Section 17.5 of the JLS gives the following example:
>
>     class FinalFieldExample {
>       final int x;
>       int y;
>       static FinalFieldExample f;
>       public FinalFieldExample() {
>         x = 3;
>         y = 4;
>       }
>       static void writer() {
>         f = new FinalFieldExample();
>       }
>       static void reader() {
>         if (f != null) {
>           int i = f.x; // guaranteed to see 3
>           int j = f.y; // could see 0
>         }
>       }
>     }
>
> Essentially, there is no guarantee that the work in the constructor has been
> completed when another thread gets a reference to the object.
>  To make the guarantee, use the final keyword.
>
> It seems like this contradicts the claim above, but maybe I'm missing
> something.
>
> TX
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]



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

Reply | Threaded
Open this post in threaded view
|

RE: Immutable OpenBitSet?

Uwe Schindler
In reply to this post by Dawid Weiss-2
The missing safe publish of the reference to the object is the problem here. Once you have published "f" safely between writer and reader, all contents and references to other objects inside the FinalFieldExample are visible.

The final modifier on this only assures in the case of no safe publish, that if for some reason the reader actually sees the object reference f!=null you then see the value of f.x. But as this is broken, you would never do this - the reader could even simply see null. Because of this you have to safe publish f, and then also f.x and f.x are correct (and then it does not matter if final or not).

To fix the example, make reader and writer synchronized, then f is published in a safe way (alternatively make f volatile). And that is what e.g. CachingWrapperFilter does (it puts the OpenBitSet into a synchronized map) - see my last mail.

-----
Uwe Schindler
H.-H.-Meier-Allee 63, D-28213 Bremen
http://www.thetaphi.de
eMail: [hidden email]


> -----Original Message-----
> From: Dawid Weiss [mailto:[hidden email]]
> Sent: Thursday, April 28, 2011 3:00 PM
> To: [hidden email]
> Subject: Re: Immutable OpenBitSet?
>
> >      static void writer() {
> >        f = new FinalFieldExample();
> >      }
> >      static void reader() {
> >        if (f != null) {
> >          int i = f.x; // guaranteed to see 3
> >          int j = f.y; // could see 0
> >        }
> >      }
> >    }
> >
>
> In this snippet of code there's not even a guarantee that reader() will see the
> change to field f... I used to create puzzlers for students around spin loops
> that got optimized away by hotspot to never again reference the
> (condition) field because the code never mutated it inside the loop. So
> something like this:
>
> while (f == null) {}
>
> should get jitted into this:
>
> while (true) {}
>
> D.


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

Reply | Threaded
Open this post in threaded view
|

RE: Immutable OpenBitSet?

Nader, John P
In reply to this post by Trejkaz
I agree that Trejkaz's example is correct and consistent with both the JLS spec and "Java Concurrency in Practice", by Goetz.  

Without synchronization, the final keyword is necessary to ensure all values set on a long[] in a constructor are seen by other threads in the state they were when the constructor completed.  This keyword allows java to insert the appropriate read barriers on the first read of the object, without the overhead of read barriers repeatedly on every read of the object.

The object construction guarantees are not enough for the long[] because these only guarantee you will see the initial array of zero's.  To guarantee safety on the subsequent writes to the long[] during the OpenBitSet constructor, the final keyword ensure those writes will be flushed to main memory when construction completes prior to any other thread getting a reference to the object.

A value holder that holds a final reference to the OpenBitSet is definitely an option as it offers that same protection.


-----Original Message-----
From: Trejkaz [mailto:[hidden email]]
Sent: Thursday, April 28, 2011 8:45 AM
To: [hidden email]
Subject: Re: Immutable OpenBitSet?

On Thu, Apr 28, 2011 at 6:13 PM, Uwe Schindler <[hidden email]> wrote:
> In general a *newly* created object that was not yet seen by any other
> thread is always safe. This is why I said, set all bits in the ctor. This is
> easy to understand: Before the ctor returns, the object's contents and all
> references like arrays are not seen by any other thread (that's guaranteed).

Section 17.5 of the JLS gives the following example:

    class FinalFieldExample {
      final int x;
      int y;
      static FinalFieldExample f;
      public FinalFieldExample() {
        x = 3;
        y = 4;
      }
      static void writer() {
        f = new FinalFieldExample();
      }
      static void reader() {
        if (f != null) {
          int i = f.x; // guaranteed to see 3
          int j = f.y; // could see 0
        }
      }
    }

Essentially, there is no guarantee that the work in the constructor
has been completed when another thread gets a reference to the object.
 To make the guarantee, use the final keyword.

It seems like this contradicts the claim above, but maybe I'm missing something.

TX

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

Reply | Threaded
Open this post in threaded view
|

RE: Immutable OpenBitSet?

Uwe Schindler
That was exactly what I demonstrated in another mail on this thread:

final OpenBitSet mybits = new OpenBitSet(size) {{
        fastSet(1); fastSet(2);...
}};

Uwe

-----
Uwe Schindler
H.-H.-Meier-Allee 63, D-28213 Bremen
http://www.thetaphi.de
eMail: [hidden email]


> -----Original Message-----
> From: Nader, John P [mailto:[hidden email]]
> Sent: Thursday, April 28, 2011 4:21 PM
> To: [hidden email]
> Subject: RE: Immutable OpenBitSet?
>
> I agree that Trejkaz's example is correct and consistent with both the JLS spec
> and "Java Concurrency in Practice", by Goetz.
>
> Without synchronization, the final keyword is necessary to ensure all values
> set on a long[] in a constructor are seen by other threads in the state they
> were when the constructor completed.  This keyword allows java to insert
> the appropriate read barriers on the first read of the object, without the
> overhead of read barriers repeatedly on every read of the object.
>
> The object construction guarantees are not enough for the long[] because
> these only guarantee you will see the initial array of zero's.  To guarantee
> safety on the subsequent writes to the long[] during the OpenBitSet
> constructor, the final keyword ensure those writes will be flushed to main
> memory when construction completes prior to any other thread getting a
> reference to the object.
>
> A value holder that holds a final reference to the OpenBitSet is definitely an
> option as it offers that same protection.
>
>
> -----Original Message-----
> From: Trejkaz [mailto:[hidden email]]
> Sent: Thursday, April 28, 2011 8:45 AM
> To: [hidden email]
> Subject: Re: Immutable OpenBitSet?
>
> On Thu, Apr 28, 2011 at 6:13 PM, Uwe Schindler <[hidden email]> wrote:
> > In general a *newly* created object that was not yet seen by any other
> > thread is always safe. This is why I said, set all bits in the ctor.
> > This is easy to understand: Before the ctor returns, the object's
> > contents and all references like arrays are not seen by any other thread
> (that's guaranteed).
>
> Section 17.5 of the JLS gives the following example:
>
>     class FinalFieldExample {
>       final int x;
>       int y;
>       static FinalFieldExample f;
>       public FinalFieldExample() {
>         x = 3;
>         y = 4;
>       }
>       static void writer() {
>         f = new FinalFieldExample();
>       }
>       static void reader() {
>         if (f != null) {
>           int i = f.x; // guaranteed to see 3
>           int j = f.y; // could see 0
>         }
>       }
>     }
>
> Essentially, there is no guarantee that the work in the constructor has been
> completed when another thread gets a reference to the object.
>  To make the guarantee, use the final keyword.
>
> It seems like this contradicts the claim above, but maybe I'm missing
> something.
>
> TX
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]



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