From: Pierangelo Masarati Date: Mon, 20 Aug 2007 00:27:47 +0000 (+0000) Subject: rework connections so that they get cached on a per-thread basis (ITS#5095) X-Git-Tag: OPENLDAP_REL_ENG_2_4_MP~168 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=4242ce20d6faad4fc79781dfab1d58149d3e105a;p=openldap rework connections so that they get cached on a per-thread basis (ITS#5095) --- diff --git a/servers/slapd/back-sql/add.c b/servers/slapd/back-sql/add.c index ed10958b67..501c8bfd96 100644 --- a/servers/slapd/back-sql/add.c +++ b/servers/slapd/back-sql/add.c @@ -1520,7 +1520,7 @@ done:; } if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &p.e_nname ) ) { diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h index 6965e3f5c9..7f336724ee 100644 --- a/servers/slapd/back-sql/back-sql.h +++ b/servers/slapd/back-sql/back-sql.h @@ -473,14 +473,16 @@ typedef struct backsql_info { */ struct berval sql_subtree_cond; struct berval sql_children_cond; - char *sql_oc_query, - *sql_at_query; - char *sql_insentry_stmt, - *sql_delentry_stmt, - *sql_renentry_stmt, - *sql_delobjclasses_stmt; + struct berval sql_dn_match_cond; + char *sql_oc_query; + char *sql_at_query; + char *sql_insentry_stmt; + char *sql_delentry_stmt; + char *sql_renentry_stmt; + char *sql_delobjclasses_stmt; char *sql_id_query; char *sql_has_children_query; + char *sql_list_children_query; MatchingRule *sql_caseIgnoreMatch; MatchingRule *sql_telephoneNumberMatch; @@ -558,9 +560,10 @@ typedef struct backsql_info { #define BACKSQL_BASEOBJECT_OC 0 Avlnode *sql_db_conns; + SQLHDBC sql_dbh; + ldap_pvt_thread_mutex_t sql_dbconn_mutex; Avlnode *sql_oc_by_oc; Avlnode *sql_oc_by_id; - ldap_pvt_thread_mutex_t sql_dbconn_mutex; ldap_pvt_thread_mutex_t sql_schema_mutex; SQLHENV sql_db_env; diff --git a/servers/slapd/back-sql/bind.c b/servers/slapd/back-sql/bind.c index 4c8f710c0b..e76b8dbca6 100644 --- a/servers/slapd/back-sql/bind.c +++ b/servers/slapd/back-sql/bind.c @@ -53,7 +53,7 @@ backsql_bind( Operation *op, SlapReply *rs ) } rs->sr_err = backsql_get_db_conn( op, &dbh ); - if ( !dbh ) { + if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_bind(): " "could not get connection handle - exiting\n", 0, 0, 0 ); @@ -94,7 +94,7 @@ backsql_bind( Operation *op, SlapReply *rs ) error_return:; if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &e.e_nname ) ) { diff --git a/servers/slapd/back-sql/compare.c b/servers/slapd/back-sql/compare.c index 8ac1d96b04..24fe2e9fb1 100644 --- a/servers/slapd/back-sql/compare.c +++ b/servers/slapd/back-sql/compare.c @@ -42,7 +42,7 @@ backsql_compare( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_TRACE, "==>backsql_compare()\n", 0, 0, 0 ); rs->sr_err = backsql_get_db_conn( op, &dbh ); - if ( !dbh ) { + if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_compare(): " "could not get connection handle - exiting\n", 0, 0, 0 ); @@ -173,7 +173,7 @@ return_results:; } if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &e.e_nname ) ) { diff --git a/servers/slapd/back-sql/config.c b/servers/slapd/back-sql/config.c index e9857fa760..db1170c884 100644 --- a/servers/slapd/back-sql/config.c +++ b/servers/slapd/back-sql/config.c @@ -148,7 +148,20 @@ backsql_db_config( } ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_children_cond ); Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " - "subtree_cond=%s\n", bi->sql_children_cond.bv_val, 0, 0 ); + "children_cond=%s\n", bi->sql_children_cond.bv_val, 0, 0 ); + + } else if ( !strcasecmp( argv[ 0 ], "dn_match_cond" ) ) { + if ( argc < 2 ) { + Debug( LDAP_DEBUG_TRACE, + "<==backsql_db_config (%s line %d): " + "missing SQL condition " + "in \"dn_match_cond\" directive\n", + fname, lineno, 0 ); + return 1; + } + ber_str2bv( argv[ 1 ], 0, 1, &bi->sql_dn_match_cond ); + Debug( LDAP_DEBUG_TRACE, "<==backsql_db_config(): " + "children_cond=%s\n", bi->sql_dn_match_cond.bv_val, 0, 0 ); } else if ( !strcasecmp( argv[ 0 ], "oc_query" ) ) { if ( argc < 2 ) { diff --git a/servers/slapd/back-sql/delete.c b/servers/slapd/back-sql/delete.c index 2bfddfda6c..8b3ec7c2ed 100644 --- a/servers/slapd/back-sql/delete.c +++ b/servers/slapd/back-sql/delete.c @@ -235,7 +235,7 @@ backsql_delete( Operation *op, SlapReply *rs ) goto done; } - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); /* check parent for "children" acl */ if ( !access_allowed( op, &p, slap_schema.si_ad_children, @@ -472,7 +472,7 @@ done:; Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 ); if ( !BER_BVISNULL( &e_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &e_id, 0 ); + (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &d.e_nname ) ) { diff --git a/servers/slapd/back-sql/entry-id.c b/servers/slapd/back-sql/entry-id.c index 22aca8c01d..b86fc477a5 100644 --- a/servers/slapd/back-sql/entry-id.c +++ b/servers/slapd/back-sql/entry-id.c @@ -36,7 +36,35 @@ struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR ); #endif /* BACKSQL_ARBITRARY_KEY */ backsql_entryID * -backsql_free_entryID( Operation *op, backsql_entryID *id, int freeit ) +backsql_entryID_dup( backsql_entryID *src, void *ctx ) +{ + backsql_entryID *dst; + + if ( src == NULL ) return NULL; + + dst = slap_sl_calloc( 1, sizeof( backsql_entryID ), ctx ); + ber_dupbv_x( &dst->eid_ndn, &src->eid_ndn, ctx ); + if ( src->eid_dn.bv_val == src->eid_ndn.bv_val ) { + dst->eid_dn = dst->eid_ndn; + } else { + ber_dupbv_x( &dst->eid_dn, &src->eid_dn, ctx ); + } + +#ifdef BACKSQL_ARBITRARY_KEY + ber_dupbv_x( &dst->eid_id, &src->eid_id, ctx ); + ber_dupbv_x( &dst->eid_keyval, &src->eid_keyval, ctx ); +#else /* ! BACKSQL_ARBITRARY_KEY */ + dst->eid_id = src->eid_id; + dst->eid_keyval = src->eid_keyval; +#endif /* ! BACKSQL_ARBITRARY_KEY */ + + dst->eid_oc_id = src->eid_oc_id; + + return dst; +} + +backsql_entryID * +backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx ) { backsql_entryID *next; @@ -48,28 +76,28 @@ backsql_free_entryID( Operation *op, backsql_entryID *id, int freeit ) if ( !BER_BVISNULL( &id->eid_dn ) && id->eid_dn.bv_val != id->eid_ndn.bv_val ) { - op->o_tmpfree( id->eid_dn.bv_val, op->o_tmpmemctx ); + slap_sl_free( id->eid_dn.bv_val, ctx ); BER_BVZERO( &id->eid_dn ); } - op->o_tmpfree( id->eid_ndn.bv_val, op->o_tmpmemctx ); + slap_sl_free( id->eid_ndn.bv_val, ctx ); BER_BVZERO( &id->eid_ndn ); } #ifdef BACKSQL_ARBITRARY_KEY if ( !BER_BVISNULL( &id->eid_id ) ) { - op->o_tmpfree( id->eid_id.bv_val, op->o_tmpmemctx ); + slap_sl_free( id->eid_id.bv_val, ctx ); BER_BVZERO( &id->eid_id ); } if ( !BER_BVISNULL( &id->eid_keyval ) ) { - op->o_tmpfree( id->eid_keyval.bv_val, op->o_tmpmemctx ); + slap_sl_free( id->eid_keyval.bv_val, ctx ); BER_BVZERO( &id->eid_keyval ); } #endif /* BACKSQL_ARBITRARY_KEY */ if ( freeit ) { - op->o_tmpfree( id, op->o_tmpmemctx ); + slap_sl_free( id, ctx ); } return next; @@ -291,7 +319,7 @@ backsql_dn2id( ldap_err2string( res ) ); /* cleanup... */ - (void)backsql_free_entryID( op, id, 0 ); + (void)backsql_free_entryID( id, 0, op->o_tmpmemctx ); } if ( dn.bv_val != row.cols[ 3 ] ) { diff --git a/servers/slapd/back-sql/init.c b/servers/slapd/back-sql/init.c index c317d3cb70..5f6bd0c2b8 100644 --- a/servers/slapd/back-sql/init.c +++ b/servers/slapd/back-sql/init.c @@ -77,7 +77,6 @@ sql_back_initialize( bi->bi_entry_release_rw = backsql_entry_release; bi->bi_connection_init = 0; - bi->bi_connection_destroy = backsql_connection_destroy; Debug( LDAP_DEBUG_TRACE,"<==sql_back_initialize()\n", 0, 0, 0 ); return 0; @@ -126,13 +125,9 @@ backsql_db_destroy( Debug( LDAP_DEBUG_TRACE, "==>backsql_db_destroy()\n", 0, 0, 0 ); - ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex ); backsql_free_db_env( bi ); - ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex ); ldap_pvt_thread_mutex_destroy( &bi->sql_dbconn_mutex ); - ldap_pvt_thread_mutex_lock( &bi->sql_schema_mutex ); backsql_destroy_schema_map( bi ); - ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex ); ldap_pvt_thread_mutex_destroy( &bi->sql_schema_mutex ); if ( bi->sql_dbname ) { @@ -161,6 +156,9 @@ backsql_db_destroy( if ( !BER_BVISNULL( &bi->sql_children_cond ) ) { ch_free( bi->sql_children_cond.bv_val ); } + if ( !BER_BVISNULL( &bi->sql_dn_match_cond ) ) { + ch_free( bi->sql_dn_match_cond.bv_val ); + } if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) { ch_free( bi->sql_subtree_cond.bv_val ); } @@ -224,12 +222,14 @@ backsql_db_open( ConfigReply *cr ) { backsql_info *bi = (backsql_info*)bd->be_private; - SQLHDBC dbh = SQL_NULL_HDBC; struct berbuf bb = BB_NULL; + Connection conn = { 0 }; OperationBuffer opbuf; Operation* op; - + SQLHDBC dbh = SQL_NULL_HDBC; + void *thrctx = ldap_pvt_thread_pool_context(); + Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): " "testing RDBMS connection\n", 0, 0, 0 ); if ( bi->sql_dbname == NULL ) { @@ -320,18 +320,20 @@ backsql_db_open( }; struct berbuf bb = BB_NULL; + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "subtree search SQL condition not specified " + "(use \"subtree_cond\" directive in slapd.conf); " + "preparing default\n", + 0, 0, 0); + if ( backsql_prepare_pattern( bi->sql_concat_func, values, &concat ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " - "unable to prepare CONCAT pattern", 0, 0, 0 ); + "unable to prepare CONCAT pattern for subtree search", + 0, 0, 0 ); return 1; } - Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " - "subtree search SQL condition not specified " - "(use \"subtree_cond\" directive in slapd.conf)\n", - 0, 0, 0); - if ( bi->sql_upper_func.bv_val ) { /* @@ -363,42 +365,112 @@ backsql_db_open( bi->sql_subtree_cond = bb.bb_val; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " - "setting \"%s\" as default\n", + "setting \"%s\" as default \"subtree_cond\"\n", bi->sql_subtree_cond.bv_val, 0, 0 ); } if ( bi->sql_children_cond.bv_val == NULL ) { + /* + * Prepare concat function for children search condition + */ + struct berval concat; + struct berval values[] = { + BER_BVC( "'%,'" ), + BER_BVC( "?" ), + BER_BVNULL + }; struct berbuf bb = BB_NULL; + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "children search SQL condition not specified " + "(use \"children_cond\" directive in slapd.conf); " + "preparing default\n", + 0, 0, 0); + + if ( backsql_prepare_pattern( bi->sql_concat_func, values, + &concat ) ) { + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "unable to prepare CONCAT pattern for children search", 0, 0, 0 ); + return 1; + } + if ( bi->sql_upper_func.bv_val ) { /* * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?)) */ - backsql_strfcat_x( &bb, NULL, "blbl", + backsql_strfcat_x( &bb, NULL, "blbbb", + &bi->sql_upper_func, + (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ), + "(ldap_entries.dn) LIKE ", + &bi->sql_upper_func_open, + &concat, + &bi->sql_upper_func_close ); + + } else { + + /* + * ldap_entries.dn LIKE CONCAT('%,',?) + */ + + backsql_strfcat_x( &bb, NULL, "lb", + (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ), + "ldap_entries.dn LIKE ", + &concat ); + } + + ch_free( concat.bv_val ); + + bi->sql_children_cond = bb.bb_val; + + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "setting \"%s\" as default \"children_cond\"\n", + bi->sql_children_cond.bv_val, 0, 0 ); + } + + if ( bi->sql_dn_match_cond.bv_val == NULL ) { + /* + * Prepare concat function for dn match search condition + */ + struct berbuf bb = BB_NULL; + + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "DN match search SQL condition not specified " + "(use \"dn_match_cond\" directive in slapd.conf); " + "preparing default\n", + 0, 0, 0); + + if ( bi->sql_upper_func.bv_val ) { + + /* + * UPPER(ldap_entries.dn)=? + */ + + backsql_strfcat_x( &bb, NULL, "blbcb", &bi->sql_upper_func, (ber_len_t)STRLENOF( "(ldap_entries.dn)=" ), "(ldap_entries.dn)=", - &bi->sql_upper_func, - (ber_len_t)STRLENOF( "(?)" ), "(?)" ); + &bi->sql_upper_func_open, + '?', + &bi->sql_upper_func_close ); } else { /* - * ldap_entries.dn LIKE CONCAT('%,',?) + * ldap_entries.dn=? */ backsql_strfcat_x( &bb, NULL, "l", (ber_len_t)STRLENOF( "ldap_entries.dn=?" ), - "ldap_entries.dn=?"); + "ldap_entries.dn=?" ); } - bi->sql_children_cond = bb.bb_val; + bi->sql_dn_match_cond = bb.bb_val; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " - "setting \"%s\" as default\n", - bi->sql_children_cond.bv_val, 0, 0 ); + "setting \"%s\" as default \"dn_match_cond\"\n", + bi->sql_dn_match_cond.bv_val, 0, 0 ); } if ( bi->sql_oc_query == NULL ) { @@ -474,17 +546,20 @@ backsql_db_open( } /* This should just be to force schema loading */ + connection_fake_init( &conn, &opbuf, thrctx ); op = &opbuf.ob_op; - op->o_hdr = &opbuf.ob_hdr; - op->o_connid = (unsigned long)(-1); op->o_bd = bd; if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "connection failed, exiting\n", 0, 0, 0 ); return 1; } - - if ( backsql_free_db_conn( op ) != SQL_SUCCESS ) { + if ( backsql_load_schema_map( bi, dbh ) != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " + "schema mapping failed, exiting\n", 0, 0, 0 ); + return 1; + } + if ( backsql_free_db_conn( op, dbh ) != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "connection free failed\n", 0, 0, 0 ); } @@ -528,7 +603,7 @@ backsql_db_open( } /* - * Prepare children ID selection query + * Prepare children count query */ BER_BVZERO( &bb.bb_val ); bb.bb_len = 0; @@ -537,7 +612,7 @@ backsql_db_open( "FROM ldap_entries,ldap_entries ", &bi->sql_aliasing, "subordinates " "WHERE subordinates.parent=ldap_entries.id AND ", - &bi->sql_children_cond ); + &bi->sql_dn_match_cond ); bi->sql_has_children_query = bb.bb_val.bv_val; /* @@ -583,23 +658,6 @@ backsql_db_close( return 0; } -int -backsql_connection_destroy( Backend *bd, Connection *c ) -{ - OperationBuffer opbuf; - Operation* op = &opbuf.ob_op; - - op->o_hdr = &opbuf.ob_hdr; - op->o_connid = c->c_connid; - op->o_bd = bd; - - Debug( LDAP_DEBUG_TRACE, "==>backsql_connection_destroy()\n", 0, 0, 0 ); - backsql_free_db_conn( op ); - Debug( LDAP_DEBUG_TRACE, "<==backsql_connection_destroy()\n", 0, 0, 0 ); - - return 0; -} - #if SLAPD_SQL == SLAPD_MOD_DYNAMIC /* conditionally define the init_module() function */ diff --git a/servers/slapd/back-sql/modify.c b/servers/slapd/back-sql/modify.c index cbd261dc46..0d84b3fef5 100644 --- a/servers/slapd/back-sql/modify.c +++ b/servers/slapd/back-sql/modify.c @@ -197,7 +197,7 @@ done:; slap_graduate_commit_csn( op ); if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &m.e_nname ) ) { diff --git a/servers/slapd/back-sql/modrdn.c b/servers/slapd/back-sql/modrdn.c index 4634078fdd..92613faba8 100644 --- a/servers/slapd/back-sql/modrdn.c +++ b/servers/slapd/back-sql/modrdn.c @@ -197,7 +197,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) } if ( newSuperior ) { - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); /* * namingContext "" is not supported @@ -407,7 +407,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' }; backsql_entry_clean( op, &r ); - (void)backsql_free_entryID( op, &e_id, 0 ); + (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); bsi.bsi_e = &r; rs->sr_err = backsql_init_search( &bsi, &new_ndn, @@ -510,11 +510,11 @@ done:; } if ( !BER_BVISNULL( &e_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &e_id, 0 ); + (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &n_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &n_id, 0 ); + (void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &r.e_nname ) ) { diff --git a/servers/slapd/back-sql/operational.c b/servers/slapd/back-sql/operational.c index 60252f6d49..f6fe6aea4f 100644 --- a/servers/slapd/back-sql/operational.c +++ b/servers/slapd/back-sql/operational.c @@ -189,7 +189,7 @@ backsql_operational( *ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id ); - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); diff --git a/servers/slapd/back-sql/proto-sql.h b/servers/slapd/back-sql/proto-sql.h index 78b9251556..3af14d5ee0 100644 --- a/servers/slapd/back-sql/proto-sql.h +++ b/servers/slapd/back-sql/proto-sql.h @@ -111,24 +111,32 @@ extern struct berval backsql_baseObject_bv; #endif /* BACKSQL_ARBITRARY_KEY */ /* stores in *id the ID in table ldap_entries corresponding to DN, if any */ -int backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh, +extern int +backsql_dn2id( Operation *op, SlapReply *rs, SQLHDBC dbh, struct berval *ndn, backsql_entryID *id, int matched, int muck ); /* stores in *nchildren the count of children for an entry */ -int backsql_count_children( Operation *op, SQLHDBC dbh, +extern int +backsql_count_children( Operation *op, SQLHDBC dbh, struct berval *dn, unsigned long *nchildren ); /* returns LDAP_COMPARE_TRUE/LDAP_COMPARE_FALSE if the entry corresponding * to DN has/has not children */ -int backsql_has_children( Operation *op, SQLHDBC dbh, struct berval *dn ); +extern int +backsql_has_children( Operation *op, SQLHDBC dbh, struct berval *dn ); -/* frees *id and returns next in list */ -backsql_entryID *backsql_free_entryID( Operation *op, backsql_entryID *id, - int freeit ); +/* free *id and return next in list */ +extern backsql_entryID * +backsql_free_entryID( backsql_entryID *id, int freeit, void *ctx ); -/* turns an ID into an entry */ -int backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id ); +/* turn an ID into an entry */ +extern int +backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *id ); + +/* duplicate an entryID */ +extern backsql_entryID * +backsql_entryID_dup( backsql_entryID *eid, void *ctx ); /* * operational.c @@ -219,9 +227,9 @@ int backsql_init_db_env( backsql_info *si ); int backsql_free_db_env( backsql_info *si ); -int backsql_get_db_conn( Operation *op, SQLHDBC *dbh ); +int backsql_get_db_conn( Operation *op, SQLHDBC *dbh ); -int backsql_free_db_conn( Operation *op ); +int backsql_free_db_conn( Operation *op, SQLHDBC dbh ); /* * util.c diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 93b7156ad0..db0ccb580e 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -1512,6 +1512,7 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) (ber_len_t)STRLENOF( "9=9"), "9=9"); } else if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) { + /* This should always be true... */ backsql_strfcat_x( &bsi->bsi_join_where, bsi->bsi_op->o_tmpmemctx, "b", @@ -1548,11 +1549,13 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) { lowid = PAGECOOKIE_TO_SQL_ID( ((PagedResultsState *)bsi->bsi_op->o_pagedresults_state)->ps_cookie ); } + if ( lowid ) { char lowidstring[48]; int lowidlen; - lowidlen = snprintf( lowidstring, 48, " AND ldap_entries.id>%d", lowid ); + lowidlen = snprintf( lowidstring, sizeof( lowidstring ), + " AND ldap_entries.id>%lu", lowid ); backsql_strfcat_x( &bsi->bsi_join_where, bsi->bsi_op->o_tmpmemctx, "l", @@ -2112,7 +2115,6 @@ backsql_search( Operation *op, SlapReply *rs ) /* If paged results are in effect, check the paging cookie */ if ( get_pagedresults( op ) > SLAP_CONTROL_IGNORED ) { - PagedResultsState *ps = op->o_pagedresults_state; rs->sr_err = parse_paged_cookie( op, rs ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); @@ -2175,9 +2177,9 @@ backsql_search( Operation *op, SlapReply *rs ) * and then send to client; don't free entry_id if baseObject... */ for ( eid = bsi.bsi_id_list; - eid != NULL; - eid = backsql_free_entryID( op, - eid, eid == &bsi.bsi_base_id ? 0 : 1 ) ) + eid != NULL; + eid = backsql_free_entryID( + eid, eid == &bsi.bsi_base_id ? 0 : 1, op->o_tmpmemctx ) ) { int rc; Attribute *a_hasSubordinate = NULL, @@ -2405,9 +2407,11 @@ backsql_search( Operation *op, SlapReply *rs ) rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_entry = e; + e->e_private = (void *)eid; rs->sr_flags = ( e == &user_entry ) ? REP_ENTRY_MODIFIABLE : 0; /* FIXME: need the whole entry (ITS#3480) */ rs->sr_err = send_search_entry( op, rs ); + e->e_private = NULL; rs->sr_entry = NULL; rs->sr_attrs = NULL; rs->sr_operational_attrs = NULL; @@ -2456,8 +2460,8 @@ send_results:; /* cleanup in case of abandon */ for ( ; eid != NULL; - eid = backsql_free_entryID( op, - eid, eid == &bsi.bsi_base_id ? 0 : 1 ) ) + eid = backsql_free_entryID( + eid, eid == &bsi.bsi_base_id ? 0 : 1, op->o_tmpmemctx ) ) ; backsql_entry_clean( op, &base_entry ); @@ -2495,7 +2499,7 @@ send_results:; #endif /* BACKSQL_SYNCPROV */ done:; - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); @@ -2538,8 +2542,8 @@ backsql_entry_get( *ent = NULL; rc = backsql_get_db_conn( op, &dbh ); - if ( !dbh ) { - return LDAP_OTHER; + if ( rc != LDAP_SUCCESS ) { + return rc; } if ( at ) { @@ -2557,7 +2561,7 @@ backsql_entry_get( BACKSQL_ISF_GET_ENTRY ); if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { - (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( rc == LDAP_SUCCESS ) { diff --git a/servers/slapd/back-sql/sql-wrap.c b/servers/slapd/back-sql/sql-wrap.c index 810fc6a4d8..5e40dc2a7b 100644 --- a/servers/slapd/back-sql/sql-wrap.c +++ b/servers/slapd/back-sql/sql-wrap.c @@ -32,11 +32,6 @@ #define MAX_ATTR_LEN 16384 -typedef struct backsql_db_conn { - unsigned long ldap_cid; - SQLHDBC dbh; -} backsql_db_conn; - void backsql_PrintErrors( SQLHENV henv, SQLHDBC hdbc, SQLHSTMT sth, int rc ) { @@ -310,29 +305,15 @@ backsql_FreeRow( BACKSQL_ROW_NTS *row ) return backsql_FreeRow_x( row, NULL ); } -static int -backsql_cmp_connid( const void *v_c1, const void *v_c2 ) -{ - const backsql_db_conn *c1 = v_c1, *c2 = v_c2; - if ( c1->ldap_cid > c2->ldap_cid ) { - return 1; - } - - if ( c1->ldap_cid < c2->ldap_cid ) { - return -1; - } - - return 0; -} - static void -backsql_close_db_conn( void *v_conn ) +backsql_close_db_handle( SQLHDBC dbh ) { - backsql_db_conn *conn = (backsql_db_conn *)v_conn; - unsigned long cid = conn->ldap_cid; + if ( dbh == SQL_NULL_HDBC ) { + return; + } - Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_conn(%lu)\n", - cid, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "==>backsql_close_db_handle(%p)\n", + (void *)dbh, 0, 0 ); /* * Default transact is SQL_ROLLBACK; commit is required only @@ -341,21 +322,18 @@ backsql_close_db_conn( void *v_conn ) */ /* TimesTen */ - SQLTransact( SQL_NULL_HENV, conn->dbh, SQL_ROLLBACK ); - SQLDisconnect( conn->dbh ); - SQLFreeConnect( conn->dbh ); - ch_free( conn ); + SQLTransact( SQL_NULL_HENV, dbh, SQL_ROLLBACK ); + SQLDisconnect( dbh ); + SQLFreeConnect( dbh ); - Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_conn(%lu)\n", - cid, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "<==backsql_close_db_handle(%p)\n", + (void *)dbh, 0, 0 ); } int backsql_conn_destroy( backsql_info *bi ) { - avl_free( bi->sql_db_conns, backsql_close_db_conn ); - return 0; } @@ -400,42 +378,44 @@ backsql_free_db_env( backsql_info *bi ) } static int -backsql_open_db_conn( backsql_info *bi, unsigned long ldap_cid, backsql_db_conn **pdbc ) +backsql_open_db_handle( + backsql_info *bi, + SQLHDBC *dbhp ) { /* TimesTen */ char DBMSName[ 32 ]; - backsql_db_conn *dbc; int rc; - assert( pdbc != NULL ); - *pdbc = NULL; + assert( dbhp != NULL ); + *dbhp = SQL_NULL_HDBC; - Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_conn(%lu)\n", - ldap_cid, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "==>backsql_open_db_handle()\n", + 0, 0, 0 ); - dbc = (backsql_db_conn *)ch_calloc( 1, sizeof( backsql_db_conn ) ); - dbc->ldap_cid = ldap_cid; - rc = SQLAllocConnect( bi->sql_db_env, &dbc->dbh ); + rc = SQLAllocConnect( bi->sql_db_env, dbhp ); if ( !BACKSQL_SUCCESS( rc ) ) { - Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): " - "SQLAllocConnect() failed:\n", ldap_cid, 0, 0 ); + Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): " + "SQLAllocConnect() failed:\n", + 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, SQL_NULL_HDBC, - SQL_NULL_HENV, rc ); + SQL_NULL_HENV, rc ); return LDAP_UNAVAILABLE; } - rc = SQLConnect( dbc->dbh, - (SQLCHAR*)bi->sql_dbname, SQL_NTS, - (SQLCHAR*)bi->sql_dbuser, SQL_NTS, - (SQLCHAR*)bi->sql_dbpasswd, SQL_NTS ); + rc = SQLConnect( *dbhp, + (SQLCHAR*)bi->sql_dbname, SQL_NTS, + (SQLCHAR*)bi->sql_dbuser, SQL_NTS, + (SQLCHAR*)bi->sql_dbpasswd, SQL_NTS ); if ( rc != SQL_SUCCESS ) { - Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): " + Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): " "SQLConnect() to database \"%s\" %s.\n", - ldap_cid, bi->sql_dbname, + bi->sql_dbname, rc == SQL_SUCCESS_WITH_INFO ? - "succeeded with info" : "failed" ); - backsql_PrintErrors( bi->sql_db_env, dbc->dbh, SQL_NULL_HENV, rc ); + "succeeded with info" : "failed", + 0 ); + backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc ); if ( rc != SQL_SUCCESS_WITH_INFO ) { + SQLFreeConnect( *dbhp ); return LDAP_UNAVAILABLE; } } @@ -444,7 +424,7 @@ backsql_open_db_conn( backsql_info *bi, unsigned long ldap_cid, backsql_db_conn * TimesTen : Turn off autocommit. We must explicitly * commit any transactions. */ - SQLSetConnectOption( dbc->dbh, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF ); + SQLSetConnectOption( *dbhp, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF ); /* * See if this connection is to TimesTen. If it is, @@ -453,112 +433,100 @@ backsql_open_db_conn( backsql_info *bi, unsigned long ldap_cid, backsql_db_conn /* Assume until proven otherwise */ bi->sql_flags &= ~BSQLF_USE_REVERSE_DN; DBMSName[ 0 ] = '\0'; - rc = SQLGetInfo( dbc->dbh, SQL_DBMS_NAME, (PTR)&DBMSName, + rc = SQLGetInfo( *dbhp, SQL_DBMS_NAME, (PTR)&DBMSName, sizeof( DBMSName ), NULL ); if ( rc == SQL_SUCCESS ) { if ( strcmp( DBMSName, "TimesTen" ) == 0 || - strcmp( DBMSName, "Front-Tier" ) == 0 ) { - Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): " - "TimesTen database!\n", ldap_cid, 0, 0 ); + strcmp( DBMSName, "Front-Tier" ) == 0 ) + { + Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): " + "TimesTen database!\n", + 0, 0, 0 ); bi->sql_flags |= BSQLF_USE_REVERSE_DN; } + } else { - Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): " - "SQLGetInfo() failed.\n", ldap_cid, 0, 0 ); - backsql_PrintErrors( bi->sql_db_env, dbc->dbh, SQL_NULL_HENV, rc ); - return rc; + Debug( LDAP_DEBUG_TRACE, "backsql_open_db_handle(): " + "SQLGetInfo() failed.\n", + 0, 0, 0 ); + backsql_PrintErrors( bi->sql_db_env, *dbhp, SQL_NULL_HENV, rc ); + SQLDisconnect( *dbhp ); + SQLFreeConnect( *dbhp ); + return LDAP_UNAVAILABLE; } /* end TimesTen */ - Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): " - "connected, adding to tree.\n", ldap_cid, 0, 0 ); - ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex ); - if ( avl_insert( &bi->sql_db_conns, dbc, backsql_cmp_connid, avl_dup_error ) ) { - Debug( LDAP_DEBUG_TRACE, "backsql_open_db_conn(%lu): " - "duplicate connection ID.\n", ldap_cid, 0, 0 ); - return LDAP_OTHER; - } - ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex ); - Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_conn(%lu)\n", ldap_cid, 0, 0 ); - - *pdbc = dbc; + Debug( LDAP_DEBUG_TRACE, "<==backsql_open_db_handle()\n", + 0, 0, 0 ); return LDAP_SUCCESS; } int -backsql_free_db_conn( Operation *op ) +backsql_free_db_conn( Operation *op, SQLHDBC dbh ) { - backsql_info *bi = (backsql_info *)op->o_bd->be_private; - backsql_db_conn tmp = { 0 }, - *conn; - Debug( LDAP_DEBUG_TRACE, "==>backsql_free_db_conn()\n", 0, 0, 0 ); - tmp.ldap_cid = op->o_connid; - ldap_pvt_thread_mutex_lock( &bi->sql_dbconn_mutex ); - conn = avl_delete( &bi->sql_db_conns, &tmp, backsql_cmp_connid ); - ldap_pvt_thread_mutex_unlock( &bi->sql_dbconn_mutex ); - /* - * we have one thread per connection, as I understand -- so we can - * get this out of critical section - */ - if ( conn != NULL ) { - Debug( LDAP_DEBUG_TRACE, "backsql_free_db_conn(): " - "closing db connection %lu (%p)\n", - op->o_connid, (void *)conn, 0 ); - backsql_close_db_conn( (void *)conn ); - } + (void)backsql_close_db_handle( dbh ); Debug( LDAP_DEBUG_TRACE, "<==backsql_free_db_conn()\n", 0, 0, 0 ); - return conn ? SQL_SUCCESS : SQL_ERROR; + return LDAP_SUCCESS; +} + +static void *backsql_db_conn_dummy; + +static void +backsql_db_conn_keyfree( + void *key, + void *data ) +{ + backsql_close_db_handle( (SQLHDBC)data ); } int -backsql_get_db_conn( Operation *op, SQLHDBC *dbh ) +backsql_get_db_conn( Operation *op, SQLHDBC *dbhp ) { - backsql_info *bi = (backsql_info *)op->o_bd->be_private; - backsql_db_conn *dbc, - tmp = { 0 }; - int rc = LDAP_SUCCESS; + backsql_info *bi = (backsql_info *)op->o_bd->be_private; + int rc = LDAP_SUCCESS; + SQLHDBC dbh = SQL_NULL_HDBC; Debug( LDAP_DEBUG_TRACE, "==>backsql_get_db_conn()\n", 0, 0, 0 ); - assert( dbh != NULL ); - *dbh = SQL_NULL_HDBC; + assert( dbhp != NULL ); + *dbhp = SQL_NULL_HDBC; - tmp.ldap_cid = op->o_connid; + if ( op->o_threadctx ) { + void *data = NULL; - /* - * we have one thread per connection, as I understand -- - * so we do not need locking here - */ - dbc = avl_find( bi->sql_db_conns, &tmp, backsql_cmp_connid ); - if ( !dbc ) { - rc = backsql_open_db_conn( bi, op->o_connid, &dbc ); - if ( rc != LDAP_SUCCESS) { - Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): " - "could not get connection handle " - "-- returning NULL\n", 0, 0, 0 ); - return rc; - } + ldap_pvt_thread_pool_getkey( op->o_threadctx, + &backsql_db_conn_dummy, &data, NULL ); + dbh = (SQLHDBC)data; + + } else { + dbh = bi->sql_dbh; } - ldap_pvt_thread_mutex_lock( &bi->sql_schema_mutex ); - if ( !BACKSQL_SCHEMA_LOADED( bi ) ) { - Debug( LDAP_DEBUG_TRACE, "backsql_get_db_conn(): " - "first call -- reading schema map\n", 0, 0, 0 ); - rc = backsql_load_schema_map( bi, dbc->dbh ); + if ( dbh == SQL_NULL_HDBC ) { + rc = backsql_open_db_handle( bi, &dbh ); if ( rc != LDAP_SUCCESS ) { - ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex ); - backsql_free_db_conn( op ); return rc; } + + if ( op->o_threadctx ) { + void *data = NULL; + + data = (void *)dbh; + ldap_pvt_thread_pool_setkey( op->o_threadctx, + &backsql_db_conn_dummy, data, + backsql_db_conn_keyfree ); + + } else { + bi->sql_dbh = dbh; + } } - ldap_pvt_thread_mutex_unlock( &bi->sql_schema_mutex ); - *dbh = dbc->dbh; + *dbhp = dbh; Debug( LDAP_DEBUG_TRACE, "<==backsql_get_db_conn()\n", 0, 0, 0 );