0081b76 slapi-nis: delay sending responses from compat tree after map search

Authored and Committed by abbra 8 years ago
    slapi-nis: delay sending responses from compat tree after map search
    
    When slapi-nis plugin responds on a search query, it holds read lock for
    the internal structure called 'map cache'. The map cache lock can also be taken
    for write when modification would be required like responding to DELETE, ADD, or
    MODIFY operations.
    
    As result of the lock semantics, write lock owner is blocked until all read lock
    owners release their locks. This is generally not a problem but when readers sent
    out LDAP query results, they call into SLAPI function that might take long time
    to send out the data due to external reasons (network latencies, clients being
    blocked, etc) and all this time map cache is locked for write operations.
    
    When Kerberos KDC issues a TGT, it needs to modify few Kerberos-related attributes
    in the principal's LDAP entry. These updates are generating MOD operations visible
    by slapi-nis plugin which triggers re-scan of map cache to potentially replace
    the affected entries. To perform potential replacement, slapi-nis has to take a write
    lock and be blocked by outstanding readers.
    
    Therefore, it is possible to encounter a situation where an LDAP client uses
    SASL GSSAPI authentication and existing Kerberos ticket did expire in a course
    of outstanding search request. According to LDAPv3 protocol specification, an
    LDAP client must perform re-negotiation before reading any outstanding PDUs. It
    would ask Kerberos KDC for a new (or renewed) TGT, that would cause MOD updates
    for the primary tree which is tracked for changes by slapi-nis. These changes
    would be blocked by a slapi-nis reader as the client cannot finish reading
    outstanding PDUs yet.
    
    To solve this problem, we avoid sending LDAP entries while keeping map cache
    lock. Instead, we generate a linked list of copies of entries which will be
    sent out. To allow sharing of entries between multiple parallel queries, we
    hash the entry and reference the cached entry in the linked list with increased
    reference count. Once entry is actually sent, its reference count decreased and
    on reaching zero it is removed from the hash.
    
    The entry in the hash table might become outdated. This is detected by comparing
    both modifyTimestamp and entryUSN values of the entry to be sent and entry in the
    hash table. If new version of the entry is different, hash table's entry reference
    is replaced with a new copy. The old entry is not removed because it is still
    referenced by some outstanding query processing. Thus, the hash table always
    references the most recent version of an entry but there might be multiple copies
    in possesion of the linked lists from the separate parallel queries.
    
    An entry sharing via hash table can be disabled by setting
            slapi-entry-cache: 0
    in the definition, cn=Schema Compatibility,cn=plugins,cn=config
    
    Resolves: rhbz#1273587
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1273587
    
        
file modified
+7 -0
file modified
+148 -11
file modified
+20 -0
file modified
+34 -0
file modified
+3 -0