Do a lazy retrieval of the LDAP schema rather than at module load.

Attempt to retrieve the schema the first time it is needed rather than
when Apache is started. A global copy is cached for future requests
for performance reasons.

The schema will be retrieved once per Apache child process.

ticket 583
This commit is contained in:
Rob Crittenden 2011-05-23 15:07:03 -04:00 committed by Martin Kosek
parent 6304d9173c
commit 868d4e734e
2 changed files with 27 additions and 18 deletions

View File

@ -600,6 +600,7 @@ class LDAPCreate(CallbackInterface, crud.Create):
)
_check_single_value_attrs(self.params, entry_attrs)
ldap.get_schema()
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True)
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False)
@ -882,6 +883,7 @@ class LDAPUpdate(LDAPQuery, crud.Update):
_check_single_value_attrs(self.params, entry_attrs)
_check_empty_attrs(self.obj.params, entry_attrs)
ldap.get_schema()
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True)
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False)

View File

@ -185,11 +185,8 @@ def get_schema(url, conn=None):
return _ldap.schema.SubSchema(schema_entry[1])
# cache schema when importing module
try:
_schema = get_schema(api.env.ldap_uri)
except AttributeError:
_schema = None
# Global schema
_schema = None
# The UPG setting will be cached the first time a module checks it
_upg = None
@ -261,7 +258,7 @@ class ldap2(CrudBackend, Encoder):
def get_syntax(self, attr, value):
if not self.schema:
return None
self.get_schema()
obj = self.schema.get_obj(_ldap.schema.AttributeType, attr)
if obj is not None:
return obj.syntax
@ -270,7 +267,7 @@ class ldap2(CrudBackend, Encoder):
def get_allowed_attributes(self, objectclasses):
if not self.schema:
return []
self.get_schema()
allowed_attributes = []
for oc in objectclasses:
obj = self.schema.get_obj(_ldap.schema.ObjectClass, oc)
@ -287,10 +284,10 @@ class ldap2(CrudBackend, Encoder):
If there is a problem loading the schema or the attribute is
not in the schema return None
"""
if self.schema:
obj = self.schema.get_obj(_ldap.schema.AttributeType, attr)
return obj and obj.single_value
return None
if not self.schema:
self.get_schema()
obj = self.schema.get_obj(_ldap.schema.AttributeType, attr)
return obj and obj.single_value
@encode_args(2, 3, 'bind_dn', 'bind_pw')
def create_connection(self, ccache=None, bind_dn='', bind_pw='',
@ -336,10 +333,8 @@ class ldap2(CrudBackend, Encoder):
except _ldap.LDAPError, e:
_handle_errors(e, **{})
if self.schema is None and _schema is None:
# explicitly use setattr here so the schema can be set after
# the object is finalized.
object.__setattr__(self, 'schema', get_schema(self.ldap_uri, conn))
if _schema:
object.__setattr__(self, 'schema', _schema)
return conn
def destroy_connection(self):
@ -656,9 +651,21 @@ class ldap2(CrudBackend, Encoder):
setattr(context, 'config_entry', copy.deepcopy(config_entry))
return (cdn, config_entry)
def get_schema(self):
"""Returns a copy of the current LDAP schema."""
return copy.deepcopy(self.schema)
def get_schema(self, deepcopy=False):
"""Returns either a reference to current schema or its deep copy"""
global _schema
if not _schema:
_schema = get_schema(self.ldap_uri, self.conn)
if not _schema:
raise errors.DatabaseError(desc='Unable to retrieve LDAP schema', info='Unable to proceed with request')
# explicitly use setattr here so the schema can be set after
# the object is finalized.
object.__setattr__(self, 'schema', _schema)
if (deepcopy):
return copy.deepcopy(self.schema)
else:
return self.schema
def has_upg(self):
"""Returns True/False whether User-Private Groups are enabled.