Re: Immutable SyntexCheckers

2017-03-20 Thread Emmanuel Lécharny


Le 20/03/2017 à 08:20, Stefan Seelmann a écrit :
> On 03/20/2017 08:12 AM, Emmanuel Lécharny wrote:
>>
>> Le 20/03/2017 à 07:37, Stefan Seelmann a écrit :
>>> On 03/20/2017 02:10 AM, Emmanuel Lécharny wrote:
 public class BooleanSyntaxChecker extends SyntaxChecker
 {
 /**
  * A static instance of BooleanSyntaxChecker
  */
 public static final BooleanSyntaxChecker INSTANCE = new
 BooleanSyntaxChecker( SchemaConstants.BOOLEAN_SYNTAX );

 /** A static instance of the builder */
 private static final Builder BUILDER_INSTANCE = new Builder();
 /**
  * @return An instance of the Builder for this class
  */
 public static Builder builder()
 {
 return BUILDER_INSTANCE;
 }
>>> Hm, why a static builder? As it is not immutable there's a chance of
>>> race condition in case two threads use it concurrently.
>> That can't happen, because we have :
>>
>> private static final Builder BUILDER_INSTANCE = new Builder();
>>
>> that is guaranteed to be built during the class loading.
> I agree about the creation of the builder instance.
>
> But if two threads *use* it:
> 1. thread 1 calls builder()
> 2. thread 2 calls builder() and gets the same builder instance
> 3. thread 1 calls setOid("1.1.1")
> 4. thread 2 calls setOid("2.2.2")
> 5. thread 1 calls build() and may get an SC with OID "2.2.2"!

Good catch...

/**
 * @return An instance of the Builder for this class
 */
public static Builder builder()
{
return new Builder();
}

would solve the issue, correct ?

(somtime, trying to verdue is wrong).


>
>

-- 
Emmanuel Lecharny

Symas.com
directory.apache.org



Re: Immutable SyntexCheckers

2017-03-20 Thread Stefan Seelmann
On 03/20/2017 08:12 AM, Emmanuel Lécharny wrote:
> 
> 
> Le 20/03/2017 à 07:37, Stefan Seelmann a écrit :
>> On 03/20/2017 02:10 AM, Emmanuel Lécharny wrote:
>>> public class BooleanSyntaxChecker extends SyntaxChecker
>>> {
>>> /**
>>>  * A static instance of BooleanSyntaxChecker
>>>  */
>>> public static final BooleanSyntaxChecker INSTANCE = new
>>> BooleanSyntaxChecker( SchemaConstants.BOOLEAN_SYNTAX );
>>>
>>> /** A static instance of the builder */
>>> private static final Builder BUILDER_INSTANCE = new Builder();
>>> /**
>>>  * @return An instance of the Builder for this class
>>>  */
>>> public static Builder builder()
>>> {
>>> return BUILDER_INSTANCE;
>>> }
>> Hm, why a static builder? As it is not immutable there's a chance of
>> race condition in case two threads use it concurrently.
> 
> That can't happen, because we have :
> 
> private static final Builder BUILDER_INSTANCE = new Builder();
> 
> that is guaranteed to be built during the class loading.

I agree about the creation of the builder instance.

But if two threads *use* it:
1. thread 1 calls builder()
2. thread 2 calls builder() and gets the same builder instance
3. thread 1 calls setOid("1.1.1")
4. thread 2 calls setOid("2.2.2")
5. thread 1 calls build() and may get an SC with OID "2.2.2"!




Re: Immutable SyntexCheckers

2017-03-20 Thread Emmanuel Lécharny


Le 20/03/2017 à 07:37, Stefan Seelmann a écrit :
> On 03/20/2017 02:10 AM, Emmanuel Lécharny wrote:
>> public class BooleanSyntaxChecker extends SyntaxChecker
>> {
>> /**
>>  * A static instance of BooleanSyntaxChecker
>>  */
>> public static final BooleanSyntaxChecker INSTANCE = new
>> BooleanSyntaxChecker( SchemaConstants.BOOLEAN_SYNTAX );
>>
>> /** A static instance of the builder */
>> private static final Builder BUILDER_INSTANCE = new Builder();
>> /**
>>  * @return An instance of the Builder for this class
>>  */
>> public static Builder builder()
>> {
>> return BUILDER_INSTANCE;
>> }
> Hm, why a static builder? As it is not immutable there's a chance of
> race condition in case two threads use it concurrently.

That can't happen, because we have :

private static final Builder BUILDER_INSTANCE = new Builder();

that is guaranteed to be built during the class loading.

-- 
Emmanuel Lecharny

Symas.com
directory.apache.org



Re: Immutable SyntexCheckers

2017-03-19 Thread Stefan Seelmann
On 03/20/2017 02:10 AM, Emmanuel Lécharny wrote:
> public class BooleanSyntaxChecker extends SyntaxChecker
> {
> /**
>  * A static instance of BooleanSyntaxChecker
>  */
> public static final BooleanSyntaxChecker INSTANCE = new
> BooleanSyntaxChecker( SchemaConstants.BOOLEAN_SYNTAX );
>
> /** A static instance of the builder */
> private static final Builder BUILDER_INSTANCE = new Builder();

> /**
>  * @return An instance of the Builder for this class
>  */
> public static Builder builder()
> {
> return BUILDER_INSTANCE;
> }

Hm, why a static builder? As it is not immutable there's a chance of
race condition in case two threads use it concurrently.



Re: Immutable SyntexCheckers

2017-03-19 Thread Emmanuel Lécharny


Le 19/03/2017 à 17:47, Emmanuel Lecharny a écrit :
> Thanks, Stefan.
>
> I'll have a look at generics tonite.
>
> Regarding the need of a builder for each class, I think it would help
> habing a consistent system across all the SCs.
>
> Otherwise, this idea should apply to the other schema objects.
>
>
> Le dim. 19 mars 2017 à 10:58, Stefan Seelmann  a
> écrit :
>
>> On 03/17/2017 11:00 AM, Emmanuel Lécharny wrote:
>> > The only requirement is that each SC has its own builder (we can't put
>> > this code in the abstract SC, because it's abstract...)
>
>> With some generics magic it should at least be possible to move common
>> stuff (setOid) to the parent.

I come with that :

in SyntaxChecker base class :

   
public abstract class SyntaxChecker extends LoadableSchemaObject
{
...
/**
 * A static Builder for this class
 */
public abstract static class SCBuilder
{
/** The SyntaxChecker OID */
protected String oid;
   
/**
 * The Builder constructor
 */
protected SCBuilder( String oid )
{
this.oid = oid;
}
   
   
/**
 * Set the SyntaxChecker's OID
 *
 * @param oid The OID
 * @return The Builder's Instance
 */
public SCBuilder setOid( String oid )
{
this.oid = oid;
   
return this;
}
   
public abstract SC build();
}


In BooleanSyntaxChecker inherited class :

public class BooleanSyntaxChecker extends SyntaxChecker
{
/**
 * A static instance of BooleanSyntaxChecker
 */
public static final BooleanSyntaxChecker INSTANCE = new
BooleanSyntaxChecker( SchemaConstants.BOOLEAN_SYNTAX );
   
/** A static instance of the builder */
private static final Builder BUILDER_INSTANCE = new Builder();
   
/**
 * A static Builder for this class
 */
public static class Builder extends SCBuilder
{
/**
 * The Builder constructor
 */
private Builder()
{
super( SchemaConstants.BOOLEAN_SYNTAX );
}
   
   
/**
 * Create a new instance of BooleanSyntaxChecker
 * @return A new instance of BooleanSyntaxChecker
 */
@Override
public BooleanSyntaxChecker build()
{
return new BooleanSyntaxChecker( oid );
}
}

   
/**
 * Creates a new instance of BooleanSyntaxChecker.
 */
private BooleanSyntaxChecker( String oid )
{
super( oid );
}

   
/**
 * @return An instance of the Builder for this class
 */
public static Builder builder()
{
return BUILDER_INSTANCE;
}

-- 
Emmanuel Lecharny

Symas.com
directory.apache.org



Re: Immutable SyntexCheckers

2017-03-19 Thread Emmanuel Lecharny
Thanks, Stefan.

I'll have a look at generics tonite.

Regarding the need of a builder for each class, I think it would help
habing a consistent system across all the SCs.

Otherwise, this idea should apply to the other schema objects.


Le dim. 19 mars 2017 à 10:58, Stefan Seelmann  a
écrit :

> On 03/17/2017 11:00 AM, Emmanuel Lécharny wrote:
> > The only requirement is that each SC has its own builder (we can't put
> > this code in the abstract SC, because it's abstract...)
>
> With some generics magic it should at least be possible to move common
> stuff (setOid) to the parent.
>
> Otherwise, I'm not sure if it's worth to create builders for all the
> "simple" syntax checkers (Boolean, DirectoryString, etc.) or if just a
> singleton immutable instance is sufficient.
>
> But in general it makes sense to have immutable syntax checkers :)
>
>
> --
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com


Re: Immutable SyntexCheckers

2017-03-19 Thread Stefan Seelmann
On 03/17/2017 11:00 AM, Emmanuel Lécharny wrote:
> The only requirement is that each SC has its own builder (we can't put
> this code in the abstract SC, because it's abstract...)

With some generics magic it should at least be possible to move common
stuff (setOid) to the parent.

Otherwise, I'm not sure if it's worth to create builders for all the
"simple" syntax checkers (Boolean, DirectoryString, etc.) or if just a
singleton immutable instance is sufficient.

But in general it makes sense to have immutable syntax checkers :)




Immutable SyntexCheckers

2017-03-17 Thread Emmanuel Lécharny
Hi guys,


last week-end, I worked on adding a way to get a static instance of
SyntaxCheckers, instead of having to create a new instance every now and
then. As most of those SC aren't going to be modified during the
lifetime of an application, it makes a lot fo sense to have it
constructed once, and only once.


First let me summarize their lifecycle.


SC (SyntaxChecker) are associated with a LDAP Syntax, and are helper
classes used to check that a value is correct, accordingly to the
AttributeType syntax. We have more or less a hundred of such objects.
Most of them are defined in the code base, and will never change, but a
few can take a parameter, like teh TelephoneNumber that can use a regexp
as a matcher.

We wanted to be able to 'inject' some new SC dynamiclaly in the server,
by using a Java class that implements a new checker (this actually
works, but it's not really use as of today). The whole idea was to make
it dead simple - sort of - to extend the Schema, adding application
driven Schema elements. Bottom line, the mechanism is in place.


Now, when do we use those SC ? When we need to check a value. In this
case, we know about the value' AttributeType, and this AT knwos about
its Syntax, which is associated with a SC. The instance are created when
we load the schema at startup, as we store the FQCN of each SC in the
Schema :


dn: m-oid=1.3.6.1.4.1.1466.115.121.1.7,ou=syntaxCheckers,cn=system,ou=schema
m-oid: 1.3.6.1.4.1.1466.115.121.1.7
m-fqcn:
org.apache.directory.api.ldap.model.schema.syntaxCheckers.BooleanSyntaxChecker
objectclass: metaSyntaxChecker
objectclass: metaTop
objectclass: top
creatorsname: uid=admin,ou=system

The relation between a Ldap Syntax and its associated SC is the OID :
they have the same. So when we load the LdapSyntax, we class load its
associated SC. As a matter of fact, LdapSyntax are just descriptive,
when SC are executable.


That being said, there is not much of a reason to have the SC being
mutable. Even for the very few ones that can use a configuration - like
a regexp -, once created, they don't change.


So I changed the existing SC code by adding a static INSTANCE, which is
a reference to the instanciated SC. You don't need anymore to create a
new instance when you need it, you just pull the INSTANCE.


That caused some issue in some tests, that were creating new instances
of a SC, but with a different OID. Using INSTANCE was breaking the
tests, because those tests were expecting a different OID. Actually, the
test was faulty, we should have created a totally new SC instead of
redefining and existing one, but well, that life and it raised a
concern. And this concern was even more important in the tests using teh
TelephoneNumber SC, because you can inject new regexp into it...

So we fixed the tests, and now, it's time to think about a better
solution, where the SC are completely immutable.


The idea is to use internal Builders :


public class BooleanSyntaxChecker extends SyntaxChecker
{

/**
 * A static instance of BooleanSyntaxChecker
 */
public static final BooleanSyntaxChecker INSTANCE = new
BooleanSyntaxChecker( SchemaConstants.BOOLEAN_SYNTAX );

/** A static instance of the builder */
private static final Builder BUILDER_INSTANCE = new Builder();

/**
 * A static Builder for this class
 */
public static class Builder
{
/** The BooleanSyntaxChecker OID */
private String oid = SchemaConstants.BOOLEAN_SYNTAX;
   
/**
 * The Builder constructor
 */
private Builder()
{
// Nothing to do
}
   
   
/**
 * Set the SyntaxChecker's OID
 *
 * @param oid The OID
 * @return The Builder's Instance
 */
public Builder setOid( String oid )
{
this.oid = oid;
   
return this;
}
   
   
/**
 * Create a new instance of BooleanSyntaxChecker
 * @return A new instance of BooleanSyntaxChecker
 */
public BooleanSyntaxChecker build()
{
return new BooleanSyntaxChecker( oid );
}
}
   
/**
 * Creates a new instance of BooleanSyntaxChecker.
 */
private BooleanSyntaxChecker( String oid )
{
super( oid );
}

   
/**
 * @return An instance of the Builder for this class
 */
public static Builder builder()
{
return BUILDER_INSTANCE;
}

The constructor is now private, so you can't instanciate the class. What
you have to do is either to get the static INSTANCE, and you get an
immutable and static version of the class, or you 'build' a completely
new instance using code like :


BooleanSyntaxChecker checker = BooleanSyntaxChecker.builder().build();

(which is actually the same as the static INSTANCE, but as a different
object), or :

BooleanSyntaxChecker checker =
BooleanSyntaxChecker.builder().setOid( "1.2.3.4"