Commit 4242ce20 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

rework connections so that they get cached on a per-thread basis (ITS#5095)

parent 3cd5308a
......@@ -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 ) ) {
......
......@@ -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;
......
......@@ -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 ) ) {
......
......@@ -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 ) ) {
......
......@@ -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 ) {
......
......@@ -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 ) ) {
......
......@@ -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 ] ) {
......
......@@ -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 */
......
......@@ -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 ) ) {
......
......@@ -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 ) ) {
......
......@@ -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 );
......
......@@ -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
......
......@@ -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;