[Freeipa-devel] Caching ldap limits for whole connection (performance)

Martin Basti mbasti at redhat.com
Wed Nov 18 16:43:20 UTC 2015



On 18.11.2015 17:34, Martin Basti wrote:
>
>
> On 18.11.2015 14:25, Petr Vobornik wrote:
>> On 11/17/2015 10:37 AM, Martin Basti wrote:
>>>
>>>
>>> On 16.11.2015 20:18, Rob Crittenden wrote:
>>>> Martin Basti wrote:
>>>>>
>>>>>
>>>>> On 16.11.2015 18:57, Martin Basti wrote:
>>>>>> How does this code work (IMO it doesn't), ldap2.py
>>>>>>
>>>>>>     def find_entries(self, filter=None, attrs_list=None, 
>>>>>> base_dn=None,
>>>>>>                      scope=_ldap.SCOPE_SUBTREE, time_limit=None,
>>>>>>                      size_limit=None, search_refs=False,
>>>>>> paged_search=False):
>>>>>>
>>>>>>         def _get_limits():
>>>>>>             """Get configured global limits, caching them for more
>>>>>> calls"""
>>>>>>             if not _lims:
>>>>>>                 config = self.get_ipa_config()
>>>>>>                 _lims['time'] = int(config.get('ipasearchtimelimit',
>>>>>> [None])[0])
>>>>>>                 _lims['size'] =
>>>>>> int(config.get('ipasearchrecordslimit', [None])[0])
>>>>>>             return _lims
>>>>>>         _lims = {}
>>>>>>
>>>>>>         if time_limit is None:
>>>>>>             time_limit = _get_limits()['time']
>>>>>>         if size_limit is None:
>>>>>>             size_limit = _get_limits()['size']
>>>>>>
>>>>>> Code above is supposed to do caching, but it doesn't do it. This 
>>>>>> might
>>>>>> work if _lims were self._lims.
>>>>>> I tried similar code to test this behavior:
>>>>>>
>>>>>> class test:
>>>>>>     def __init__(self):
>>>>>>        pass
>>>>>>
>>>>>>     def cached_call(self):
>>>>>>        """configured global limits"""
>>>>>>        _lims = {}
>>>>>>        def _get_limits():
>>>>>>            if not _lims:
>>>>>>                _lims['t']='oujeee'
>>>>>>                print 'getting limits'
>>>>>>            return _lims
>>>>>>
>>>>>>        print "Limits:", _get_limits()['t']
>>>>>>
>>>>>> t = test()
>>>>>> t.cached_call()
>>>>>> t.cached_call()
>>>>>> t.cached_call()
>>>>>> t.cached_call()
>>>>>>
>>>>>> Output:
>>>>>> $ python testcaching.py
>>>>>> Limits: getting limits
>>>>>> oujeee
>>>>>> Limits: getting limits
>>>>>> oujeee
>>>>>> Limits: getting limits
>>>>>> oujeee
>>>>>> Limits: getting limits
>>>>>> oujeee
>>>>>>
>>>>>> So it does not do caching, or am I wrong?
>>>>>> Martin^2
>>>>>>
>>>>> That code works, the whole caching is just for the second call of
>>>>> _get_limits()
>>>>>
>>>>> Can we instead just caching limits for second use, do caching for 
>>>>> whole
>>>>> connection?
>>>>> This may be effective for methods/commands that calls search and show
>>>>> several times.
>>>>>
>>>>> Is there something that prevents us to do that?
>>>>>
>>>>
>>>> It already is cached. See get_ipa_config().
>>>>
>>>> rob
>>> I missed that part there, thank you.
>>> Martin
>>>
>>
>> I tried user_add and according to access log( 
>> http://fpaste.org/291835/44785307/ ) it alone does 13 searches for 
>> ipa config:
>>
>> SRCH base="cn=ipaconfig,cn=etc,dc=example.com" scope=0 
>> filter="(objectClass=*)" attrs=ALL
>>
>> So I think it is not working correctly.
>
> I did testing, I put following debug prints into get_ipa_config method:
>
> +       print("call: get_ipa_config")
>         try:
>             config_entry = getattr(context, 'config_entry')
>             if config_entry.conn is self.conn:
>                 return config_entry
> +            print("get_ipa_config: different connection!")
>         except AttributeError:
>             # Not in our context yet
>             pass
>
> then I restarted apache, executed "ipa user-add test2" and result is 
> here: http://fpaste.org/291926/64204144/
>
> what means that the check in get_ipa_config is wrong, or ipa framework 
> always creates a new connection.
> Except the first call that does not have cached value in context, 
> every other call asked directly LDAP for the value.
>
The comparation of connections in get_ipa_config does not work.
http://fpaste.org/291937/64863144/

I added repr(connection) of cached and current connection, and self.conn 
is still the same but *is* operator returned failed.




More information about the Freeipa-devel mailing list