]> git.sur5r.net Git - openldap/commitdiff
keep count of requests in use
authorPierangelo Masarati <ando@openldap.org>
Fri, 1 Sep 2006 14:00:58 +0000 (14:00 +0000)
committerPierangelo Masarati <ando@openldap.org>
Fri, 1 Sep 2006 14:00:58 +0000 (14:00 +0000)
libraries/libldap/ldap-int.h
libraries/libldap/request.c
libraries/libldap/result.c

index 9863b32b60c49a32cd054749ecec886a2012b061..2276ac6e5467309fd1226059df5b8aa666aad342 100644 (file)
@@ -263,23 +263,24 @@ typedef struct ldap_conn {
  * structure used to track outstanding requests
  */
 typedef struct ldapreq {
-       ber_int_t               lr_msgid;       /* the message id */
+       ber_int_t       lr_msgid;       /* the message id */
        int             lr_status;      /* status of request */
 #define LDAP_REQST_COMPLETED   0
 #define LDAP_REQST_INPROGRESS  1
 #define LDAP_REQST_CHASINGREFS 2
 #define LDAP_REQST_NOTCONNECTED        3
 #define LDAP_REQST_WRITING     4
+       int             lr_refcnt;      /* count of references */
        int             lr_outrefcnt;   /* count of outstanding referrals */
-       ber_int_t               lr_origid;      /* original request's message id */
+       ber_int_t       lr_origid;      /* original request's message id */
        int             lr_parentcnt;   /* count of parent requests */
-       ber_tag_t               lr_res_msgtype; /* result message type */
-       ber_int_t               lr_res_errno;   /* result LDAP errno */
+       ber_tag_t       lr_res_msgtype; /* result message type */
+       ber_int_t       lr_res_errno;   /* result LDAP errno */
        char            *lr_res_error;  /* result error string */
        char            *lr_res_matched;/* result matched DN string */
        BerElement      *lr_ber;        /* ber encoded request contents */
        LDAPConn        *lr_conn;       /* connection used to send request */
-       struct berval   lr_dn;  /* DN of request, in lr_ber */
+       struct berval   lr_dn;          /* DN of request, in lr_ber */
        struct ldapreq  *lr_parent;     /* request that spawned this referral */
        struct ldapreq  *lr_child;      /* first child request */
        struct ldapreq  *lr_refnext;    /* next referral spawned */
@@ -532,6 +533,7 @@ LDAP_F (void) ldap_set_ber_options( LDAP *ld, BerElement *ber );
 LDAP_F (int) ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind );
 LDAP_F (LDAPConn *) ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind );
 LDAP_F (LDAPRequest *) ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid );
+LDAP_F (void) ldap_return_request_by_msgid( LDAP *ld, LDAPRequest *lr, int freeit );
 LDAP_F (void) ldap_free_request( LDAP *ld, LDAPRequest *lr );
 LDAP_F (void) ldap_free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind );
 LDAP_F (void) ldap_dump_connection( LDAP *ld, LDAPConn *lconns, int all );
index c140dc73b9d5905b52b363f9637f24812952122e..6e923158fff2145d30734ab658c0ed87fc1c449c 100644 (file)
@@ -293,7 +293,8 @@ ldap_send_server_request(
        }
 
        lr->lr_prev = NULL;
-       if (( lr->lr_next = ld->ld_requests ) != NULL ) {
+       lr->lr_next = ld->ld_requests;
+       if ( lr->lr_next != NULL ) {
                lr->lr_next->lr_prev = lr;
        }
        ld->ld_requests = lr;
@@ -740,10 +741,20 @@ ldap_dump_requests_and_responses( LDAP *ld )
 static void
 ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
 {
+       /* if lr_refcnt > 0, the request has been looked up 
+        * by ldap_find_request_by_msgid(); if in the meanwhile
+        * the request is free()'d by someone else, just decrease
+        * the reference count and extract it from the request
+        * list; later on, it will be freed. */
        if ( lr->lr_prev == NULL ) {
-               /* free'ing the first request? */
-               assert( ld->ld_requests == lr );
-               ld->ld_requests = lr->lr_next;
+               if ( lr->lr_refcnt == 0 ) {
+                       /* free'ing the first request? */
+                       assert( ld->ld_requests == lr );
+               }
+
+               if ( ld->ld_requests == lr ) {
+                       ld->ld_requests = lr->lr_next;
+               }
 
        } else {
                lr->lr_prev->lr_next = lr->lr_next;
@@ -753,6 +764,15 @@ ldap_free_request_int( LDAP *ld, LDAPRequest *lr )
                lr->lr_next->lr_prev = lr->lr_prev;
        }
 
+       if ( lr->lr_refcnt > 0 ) {
+               lr->lr_refcnt = -lr->lr_refcnt;
+
+               lr->lr_prev = NULL;
+               lr->lr_next = NULL;
+
+               return;
+       }
+
        if ( lr->lr_ber != NULL ) {
                ber_free( lr->lr_ber, 1 );
                lr->lr_ber = NULL;
@@ -788,8 +808,10 @@ ldap_free_request( LDAP *ld, LDAPRequest *lr )
 
        if ( lr->lr_parent != NULL ) {
                --lr->lr_parent->lr_outrefcnt;
-               for ( ttmplr = &lr->lr_parent->lr_child; *ttmplr && *ttmplr != lr; ttmplr = &(*ttmplr)->lr_refnext ); 
-               if ( *ttmplr == lr )  
+               for ( ttmplr = &lr->lr_parent->lr_child;
+                       *ttmplr && *ttmplr != lr;
+                       ttmplr = &(*ttmplr)->lr_refnext );
+               if ( *ttmplr == lr )
                        *ttmplr = lr->lr_refnext;
        }
        ldap_free_request_int( ld, lr );
@@ -1422,6 +1444,7 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
                        continue;       /* Skip completed requests */
                }
                if ( msgid == lr->lr_msgid ) {
+                       lr->lr_refcnt++;
                        break;
                }
        }
@@ -1432,4 +1455,35 @@ ldap_find_request_by_msgid( LDAP *ld, ber_int_t msgid )
        return( lr );
 }
 
+void
+ldap_return_request_by_msgid( LDAP *ld, LDAPRequest *lrx, int freeit )
+{
+       LDAPRequest     *lr;
 
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
+#endif
+       for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
+               if ( lr == lrx ) {
+                       if ( lr->lr_refcnt > 0 ) {
+                               lr->lr_refcnt--;
+
+                       } else if ( lr->lr_refcnt < 0 ) {
+                               lr->lr_refcnt++;
+                               if ( lr->lr_refcnt == 0 ) {
+                                       lr = NULL;
+                               }
+                       }
+                       break;
+               }
+       }
+       if ( lr == NULL ) {
+               ldap_free_request_int( ld, lrx );
+
+       } else if ( freeit ) {
+               ldap_free_request( ld, lrx );
+       }
+#ifdef LDAP_R_COMPILE
+       ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
+#endif
+}
index 1226e19316c33988643e261797a95801dd2d296d..b9d1e03732219f3ed4f2b46432dc3697047aaa0a 100644 (file)
@@ -337,6 +337,7 @@ wait4msg(
 
                                if ( rc == -1 ) {
                                        rc = LDAP_MSG_X_KEEP_LOOKING;   /* select interrupted: loop */
+
                                } else {
                                        rc = LDAP_MSG_X_KEEP_LOOKING;
 #ifdef LDAP_R_COMPILE
@@ -577,6 +578,7 @@ nextresp2:
                                /* Get the referral list */
                                if ( ber_scanf( &tmpber, "{v}", &refs ) == LBER_ERROR ) {
                                        rc = LDAP_DECODING_ERROR;
+
                                } else {
                                        /* Note: refs array is freed by ldap_chase_v3referrals */
                                        refer_cnt = ldap_chase_v3referrals( ld, lr, refs,
@@ -598,6 +600,7 @@ nextresp2:
                                        }
                                }
                        }
+
                } else {
                        /* Check for V3 referral */
                        ber_len_t       len;
@@ -608,14 +611,12 @@ nextresp2:
                                    != LBER_ERROR )
                        {
                                if ( lr_res_error != NULL ) {
-                                       {
-                                               if ( lr->lr_res_error != NULL ) {
-                                                       (void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error );
-                                                       LDAP_FREE( (char *)lr_res_error );
+                                       if ( lr->lr_res_error != NULL ) {
+                                               (void)ldap_append_referral( ld, &lr->lr_res_error, lr_res_error );
+                                               LDAP_FREE( (char *)lr_res_error );
 
-                                               } else {
-                                                       lr->lr_res_error = lr_res_error;
-                                               }
+                                       } else {
+                                               lr->lr_res_error = lr_res_error;
                                        }
                                        lr_res_error = NULL;
                                }
@@ -637,6 +638,7 @@ nextresp2:
                                                        Debug( LDAP_DEBUG_TRACE,
                                                                "read1msg: referral decode error, mark request completed, ld %p msgid %d\n",
                                                                (void *)ld, lr->lr_msgid, 0);
+
                                                } else {
                                                        /* Chase the referral 
                                                         * Note: refs arrary is freed by ldap_chase_v3referrals
@@ -659,6 +661,7 @@ nextresp2:
                                        LDAP_FREE( lr->lr_res_matched );
                                        lr->lr_res_matched = NULL;
                                }
+
                                if( lr->lr_res_error != NULL ) {
                                        LDAP_FREE( lr->lr_res_error );
                                        lr->lr_res_error = NULL;
@@ -690,6 +693,7 @@ nextresp2:
                                 */
                                if ( tag == LDAP_RES_SEARCH_RESULT )
                                        refer_cnt = 0;
+
                        } else if ( ber_scanf( &tmpber, "{eAA}", &lderr,
                                &lr->lr_res_matched, &lr_res_error )
                                != LBER_ERROR )
@@ -733,8 +737,10 @@ nextresp2:
                                        lr->lr_res_errno = ( lderr ==
                                        LDAP_PARTIAL_RESULTS ) ? LDAP_SUCCESS
                                        : lderr;
+
                                } else if ( ld->ld_errno != LDAP_SUCCESS ) {
                                        lr->lr_res_errno = ld->ld_errno;
+
                                } else {
                                        lr->lr_res_errno = LDAP_PARTIAL_RESULTS;
                                }
@@ -762,13 +768,16 @@ nextresp2:
                        ber_free( ber, 1 );
                        ber = NULL;
                        if ( refer_cnt < 0 ) {
+                               ldap_return_request_by_msgid( ld, lr, 0 );
                                return( -1 );   /* fatal error */
                        }
                        lr->lr_res_errno = LDAP_SUCCESS; /* sucessfully chased referral */
+
                } else {
                        if ( lr->lr_outrefcnt <= 0 && lr->lr_parent == NULL ) {
                                /* request without any referrals */
                                simple_request = ( hadref ? 0 : 1 );
+
                        } else {
                                /* request with referrals or child request */
                                ber_free( ber, 1 );
@@ -791,9 +800,9 @@ nextresp2:
                        /* Check if all requests are finished, lr is now parent */
                        tmplr = lr;
                        if ( tmplr->lr_status == LDAP_REQST_COMPLETED ) {
-                               for ( tmplr=lr->lr_child;
+                               for ( tmplr = lr->lr_child;
                                        tmplr != NULL;
-                                       tmplr=tmplr->lr_refnext)
+                                       tmplr = tmplr->lr_refnext )
                                {
                                        if ( tmplr->lr_status != LDAP_REQST_COMPLETED ) break;
                                }
@@ -821,13 +830,8 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
                                        }
                                }
 
-#ifdef LDAP_R_COMPILE
-                               ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
-#endif
-                               ldap_free_request( ld, lr );
-#ifdef LDAP_R_COMPILE
-                               ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
-#endif
+                               ldap_return_request_by_msgid( ld, lr, 1 );
+                               lr = NULL;
                        }
 
                        if ( lc != NULL ) {
@@ -843,6 +847,11 @@ lr->lr_res_matched ? lr->lr_res_matched : "" );
                }
        }
 
+       if ( lr != NULL ) {
+               ldap_return_request_by_msgid( ld, lr, 0 );
+               lr = NULL;
+       }
+
        if ( ber == NULL ) {
                return( rc );
        }