From: Howard Chu Date: Thu, 29 Aug 2002 12:12:36 +0000 (+0000) Subject: Fix ITS#1983, handle writing of large requests. Only one pending request is X-Git-Tag: NO_SLAP_OP_BLOCKS~1112 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=456e6c73abe4920da074c9a0e4561267808ef81e;p=openldap Fix ITS#1983, handle writing of large requests. Only one pending request is allowed per LDAP* handle. It works, but needs review. --- diff --git a/libraries/libldap/abandon.c b/libraries/libldap/abandon.c index a88a5865b5..04397a275e 100644 --- a/libraries/libldap/abandon.c +++ b/libraries/libldap/abandon.c @@ -224,7 +224,7 @@ do_abandon( } if ( lr != NULL ) { - if ( sendabandon ) { + if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) { ldap_free_connection( ld, lr->lr_conn, 0, 1 ); } if ( origid == msgid ) { diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 4ad20dd9f4..5e44c3287d 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -467,6 +467,7 @@ LDAP_F (int) ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, LDAP_F (int) ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **referralsp, int *hadrefp ); LDAP_F (int) ldap_append_referral( LDAP *ld, char **referralsp, char *s ); +LDAP_F (int) ldap_int_flush_request( LDAP *ld, LDAPRequest *lr ); /* * in result.c: diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index b9ecd9b3bd..c45a7769f5 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -137,6 +137,39 @@ ldap_send_initial_request( } +int +ldap_int_flush_request( + LDAP *ld, + LDAPRequest *lr +) +{ + LDAPConn *lc = lr->lr_conn; + + if ( ber_flush( lc->lconn_sb, lr->lr_ber, 0 ) != 0 ) { + if ( errno == EWOULDBLOCK || errno == EAGAIN ) { + /* need to continue write later */ + lr->lr_status = LDAP_REQST_WRITING; + ldap_mark_select_write( ld, lc->lconn_sb ); + ld->ld_errno = LDAP_BUSY; + return -2; + } else { + ld->ld_errno = LDAP_SERVER_DOWN; + ldap_free_request( ld, lr ); + ldap_free_connection( ld, lc, 0, 0 ); + return( -1 ); + } + } else { + if ( lr->lr_parent == NULL ) { + lr->lr_ber->ber_end = lr->lr_ber->ber_ptr; + lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf; + } + lr->lr_status = LDAP_REQST_INPROGRESS; + + /* sent -- waiting for a response */ + ldap_mark_select_read( ld, lc->lconn_sb ); + } + return 0; +} int ldap_send_server_request( @@ -189,6 +222,18 @@ ldap_send_server_request( } use_connection( ld, lc ); + + /* If we still have an incomplete write, try to finish it before + * dealing with the new request. If we don't finish here, return + * LDAP_BUSY and let the caller retry later. We only allow a single + * request to be in WRITING state. + */ + if ( ld->ld_requests && + ld->ld_requests->lr_status == LDAP_REQST_WRITING && + ldap_int_flush_request( ld, ld->ld_requests ) < 0 ) { + return -1; + } + if (( lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ))) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; @@ -225,30 +270,8 @@ ldap_send_server_request( ld->ld_requests = lr; lr->lr_prev = NULL; - if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) { -#ifdef notyet - if ( errno == EWOULDBLOCK ) { - /* need to continue write later */ - lr->lr_status = LDAP_REQST_WRITING; - ldap_mark_select_write( ld, lc->lconn_sb ); - } else { -#else /* notyet */ - ld->ld_errno = LDAP_SERVER_DOWN; - ldap_free_request( ld, lr ); - ldap_free_connection( ld, lc, 0, 0 ); - return( -1 ); -#endif /* notyet */ -#ifdef notyet - } -#endif /* notyet */ - } else { - if ( parentreq == NULL ) { - ber->ber_end = ber->ber_ptr; - ber->ber_ptr = ber->ber_buf; - } - - /* sent -- waiting for a response */ - ldap_mark_select_read( ld, lc->lconn_sb ); + if ( ldap_int_flush_request( ld, lr ) == -1 ) { + return -1; } ld->ld_errno = LDAP_SUCCESS; diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index 1a7bcec9ef..2f82aa9422 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -334,6 +334,12 @@ wait4msg( rc = -2; /* select interrupted: loop */ } else { rc = -2; + if ( ld->ld_requests && + ld->ld_requests->lr_status == LDAP_REQST_WRITING && + ldap_is_write_ready( ld, + ld->ld_requests->lr_conn->lconn_sb ) ) { + ldap_int_flush_request( ld, ld->ld_requests ); + } for ( lc = ld->ld_conns; rc == -2 && lc != NULL; lc = nextlc ) { nextlc = lc->lconn_next;