From 75999a18c3c302bc2a71e9a01dfe63a62be8077c Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Mon, 16 Jan 2017 21:21:33 +0000 Subject: [PATCH] ITS#8725 Add SLAPD_ASYNCOP return code Tell frontend the op will finish asynchronously, leave it alone --- servers/slapd/add.c | 5 +++++ servers/slapd/backover.c | 12 +++++++++++- servers/slapd/compare.c | 4 ++++ servers/slapd/connection.c | 31 +++++++++++++++++++++++++++++++ servers/slapd/delete.c | 4 ++++ servers/slapd/modify.c | 4 ++++ servers/slapd/modrdn.c | 5 +++++ servers/slapd/proto-slap.h | 3 +++ servers/slapd/search.c | 4 ++++ servers/slapd/slap.h | 3 +++ 10 files changed, 74 insertions(+), 1 deletion(-) diff --git a/servers/slapd/add.c b/servers/slapd/add.c index 99b8656dce..d0b3b772fd 100644 --- a/servers/slapd/add.c +++ b/servers/slapd/add.c @@ -194,6 +194,11 @@ do_add( Operation *op, SlapReply *rs ) rc = frontendDB->be_add( op, rs ); LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next); + if ( rc == SLAPD_ASYNCOP ) { + /* skip cleanup */ + return rc; + } + #ifdef LDAP_X_TXN if ( rc == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ diff --git a/servers/slapd/backover.c b/servers/slapd/backover.c index 8914920998..a673fb36c6 100644 --- a/servers/slapd/backover.c +++ b/servers/slapd/backover.c @@ -717,6 +717,16 @@ cleanup: return rc; } +static int +over_op_func_cleanup( Operation *op, SlapReply *rs ) +{ + slap_callback *cb = op->o_callback; + if ( rs->sr_type == REP_RESULT && cb != NULL) { + op->o_callback = cb->sc_next; + ch_free( cb ); + } +} + static int over_op_func( Operation *op, @@ -743,7 +753,7 @@ over_op_func( db.be_flags |= SLAP_DBFLAG_OVERLAY; op->o_bd = &db; } - cb->sc_cleanup = NULL; + cb->sc_cleanup = over_op_func_cleanup; cb->sc_response = over_back_response; cb->sc_writewait = NULL; cb->sc_next = op->o_callback; diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index a656e12b05..b36062d395 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -125,6 +125,10 @@ do_compare( op->o_bd = frontendDB; rs->sr_err = frontendDB->be_compare( op, rs ); + if ( rs->sr_err == SLAPD_ASYNCOP ) { + /* skip cleanup */ + return rs->sr_err; + } cleanup:; op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx ); diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 5fe8d148fd..4d464b0b45 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -1040,6 +1040,26 @@ conn_counter_init( Operation *op, void *ctx ) op->o_counters = vsc; } +void +connection_op_finish( Operation *op ) +{ + Connection *conn = op->o_conn; + void *memctx_null = NULL; + + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); + + if ( op->o_tag == LDAP_REQ_BIND && conn->c_conn_state == SLAP_C_BINDING ) + conn->c_conn_state = SLAP_C_ACTIVE; + + ber_set_option( op->o_ber, LBER_OPT_BER_MEMCTX, &memctx_null ); + + LDAP_STAILQ_REMOVE( &conn->c_ops, op, Operation, o_next); + LDAP_STAILQ_NEXT(op, o_next) = NULL; + conn->c_n_ops_executing--; + conn->c_n_ops_completed++; + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); +} + static void * connection_operation( void *ctx, void *arg_v ) { @@ -1147,6 +1167,17 @@ operations_error: if ( rc == SLAPD_DISCONNECT ) { tag = LBER_ERROR; + } else if ( rc == SLAPD_ASYNCOP ) { + /* someone has claimed ownership of the op + * to complete it later. Don't do anything + * else with it now. Detach memctx too. + */ + slap_sl_mem_setctx( ctx, NULL ); + ldap_pvt_thread_mutex_lock( &conn->c_mutex ); + connection_resched( conn ); + ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + return NULL; + } else if ( opidx != SLAP_OP_LAST ) { /* increment completed operations count * only if operation was initiated diff --git a/servers/slapd/delete.c b/servers/slapd/delete.c index 7afcfeabe2..70a3354345 100644 --- a/servers/slapd/delete.c +++ b/servers/slapd/delete.c @@ -93,6 +93,10 @@ do_delete( op->o_bd = frontendDB; rs->sr_err = frontendDB->be_delete( op, rs ); + if ( rs->sr_err == SLAPD_ASYNCOP ) { + /* skip cleanup */ + return rs->sr_err; + } #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c index a554cf71c3..d074ce2746 100644 --- a/servers/slapd/modify.c +++ b/servers/slapd/modify.c @@ -175,6 +175,10 @@ do_modify( op->o_bd = frontendDB; rs->sr_err = frontendDB->be_modify( op, rs ); + if ( rs->sr_err == SLAPD_ASYNCOP ) { + /* skip cleanup */ + return rs->sr_err; + } #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { diff --git a/servers/slapd/modrdn.c b/servers/slapd/modrdn.c index 23579c1e98..67340f2f5e 100644 --- a/servers/slapd/modrdn.c +++ b/servers/slapd/modrdn.c @@ -185,9 +185,14 @@ do_modrdn( op->o_bd = frontendDB; rs->sr_err = frontendDB->be_modrdn( op, rs ); + if ( rs->sr_err == SLAPD_ASYNCOP ) { + /* skip cleanup */ + return rs->sr_err; + } #ifdef LDAP_X_TXN if( rs->sr_err == LDAP_X_TXN_SPECIFY_OKAY ) { /* skip cleanup */ + return rs->sr_err; } #endif diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 9d3d39bfe1..7478067ea4 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -806,6 +806,9 @@ LDAP_SLAPD_F (const char *) connection_state2str LDAP_P(( int state )) LDAP_SLAPD_F (int) connection_read_activate LDAP_P((ber_socket_t s)); LDAP_SLAPD_F (int) connection_write LDAP_P((ber_socket_t s)); +LDAP_SLAPD_F (void) connection_op_finish LDAP_P(( + Operation *op )); + LDAP_SLAPD_F (unsigned long) connections_nextid(void); LDAP_SLAPD_F (Connection *) connection_first LDAP_P(( ber_socket_t * )); diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 74bd3f219e..01b90e3d9b 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -245,6 +245,10 @@ do_search( op->o_bd = frontendDB; rs->sr_err = frontendDB->be_search( op, rs ); + if ( rs->sr_err == SLAPD_ASYNCOP ) { + /* skip cleanup */ + return rs->sr_err; + } return_results:; if ( !BER_BVISNULL( &op->o_req_dn ) ) { diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index e401650a86..ede7b793da 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -155,6 +155,9 @@ LDAP_BEGIN_DECL /* unknown config file directive */ #define SLAP_CONF_UNKNOWN (-1026) +/* pseudo error code indicating async operation */ +#define SLAPD_ASYNCOP (-1027) + /* We assume "C" locale, that is US-ASCII */ #define ASCII_SPACE(c) ( (c) == ' ' ) #define ASCII_LOWER(c) ( (c) >= 'a' && (c) <= 'z' ) -- 2.39.5