From 71511a05697269ac8a0a1f54d1fd4438894dc03f Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Wed, 8 Mar 2006 05:54:10 +0000 Subject: [PATCH] more txn infrastructure --- servers/slapd/back-bdb/add.c | 16 +++++++++++++--- servers/slapd/back-bdb/delete.c | 16 +++++++++++++--- servers/slapd/back-bdb/modify.c | 16 +++++++++++++--- servers/slapd/back-bdb/modrdn.c | 16 +++++++++++++--- servers/slapd/connection.c | 25 +++++++++++++++++++++++-- servers/slapd/slap.h | 11 +++++++---- servers/slapd/txn.c | 25 +++++++++++++++++++++---- 7 files changed, 103 insertions(+), 22 deletions(-) diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index 3cafbe42cb..5fa8f7981e 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -44,6 +44,10 @@ bdb_add(Operation *op, SlapReply *rs ) LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; +#ifdef LDAP_X_TXN + int settle = 0; +#endif + Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_add) ": %s\n", op->oq_add.rs_e->e_name.bv_val, 0, 0); @@ -51,11 +55,15 @@ bdb_add(Operation *op, SlapReply *rs ) if( op->o_txnSpec ) { /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - if( op->o_conn->c_txn == 0 ) { + if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) { rs->sr_text = "invalid transaction identifier"; rs->sr_err = LDAP_X_TXN_ID_INVALID; goto txnReturn; + } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) { + settle=1; + goto txnReturn; } + if( op->o_conn->c_txn_backend == NULL ) { op->o_conn->c_txn_backend = op->o_bd; @@ -74,8 +82,10 @@ txnReturn: /* release connection lock */ ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); - send_ldap_result( op, rs ); - return rs->sr_err; + if( !settle ) { + send_ldap_result( op, rs ); + return rs->sr_err; + } } #endif diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index 60fa54f9a1..488cdafd3b 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -52,6 +52,10 @@ bdb_delete( Operation *op, SlapReply *rs ) int parent_is_glue = 0; int parent_is_leaf = 0; +#ifdef LDAP_X_TXN + int settle = 0; +#endif + Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(bdb_delete) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); @@ -59,11 +63,15 @@ bdb_delete( Operation *op, SlapReply *rs ) if( op->o_txnSpec ) { /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - if( op->o_conn->c_txn == 0 ) { + if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) { rs->sr_text = "invalid transaction identifier"; rs->sr_err = LDAP_X_TXN_ID_INVALID; goto txnReturn; + } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) { + settle=1; + goto txnReturn; } + if( op->o_conn->c_txn_backend == NULL ) { op->o_conn->c_txn_backend = op->o_bd; @@ -82,8 +90,10 @@ txnReturn: /* release connection lock */ ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); - send_ldap_result( op, rs ); - return rs->sr_err; + if( !settle ) { + send_ldap_result( op, rs ); + return rs->sr_err; + } } #endif diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index 7ad798b480..19cd76f4ab 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -293,6 +293,10 @@ bdb_modify( Operation *op, SlapReply *rs ) int rc; +#ifdef LDAP_X_TXN + int settle = 0; +#endif + Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(bdb_modify) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); @@ -300,11 +304,15 @@ bdb_modify( Operation *op, SlapReply *rs ) if( op->o_txnSpec ) { /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - if( op->o_conn->c_txn == 0 ) { + if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) { rs->sr_text = "invalid transaction identifier"; rs->sr_err = LDAP_X_TXN_ID_INVALID; goto txnReturn; + } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) { + settle=1; + goto txnReturn; } + if( op->o_conn->c_txn_backend == NULL ) { op->o_conn->c_txn_backend = op->o_bd; @@ -323,8 +331,10 @@ txnReturn: /* release connection lock */ ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); - send_ldap_result( op, rs ); - return rs->sr_err; + if( !settle ) { + send_ldap_result( op, rs ); + return rs->sr_err; + } } #endif diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index 23d28810af..f32abdf567 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -61,6 +61,10 @@ bdb_modrdn( Operation *op, SlapReply *rs ) int parent_is_glue = 0; int parent_is_leaf = 0; +#ifdef LDAP_X_TXN + int settle = 0; +#endif + Debug( LDAP_DEBUG_TRACE, "==>" LDAP_XSTRING(bdb_modrdn) "(%s,%s,%s)\n", op->o_req_dn.bv_val,op->oq_modrdn.rs_newrdn.bv_val, op->oq_modrdn.rs_newSup ? op->oq_modrdn.rs_newSup->bv_val : "NULL" ); @@ -69,11 +73,15 @@ bdb_modrdn( Operation *op, SlapReply *rs ) if( op->o_txnSpec ) { /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - if( op->o_conn->c_txn == 0 ) { + if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) { rs->sr_text = "invalid transaction identifier"; rs->sr_err = LDAP_X_TXN_ID_INVALID; goto txnReturn; + } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) { + settle=1; + goto txnReturn; } + if( op->o_conn->c_txn_backend == NULL ) { op->o_conn->c_txn_backend = op->o_bd; @@ -92,8 +100,10 @@ txnReturn: /* release connection lock */ ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); - send_ldap_result( op, rs ); - return rs->sr_err; + if( !settle ) { + send_ldap_result( op, rs ); + return rs->sr_err; + } } #endif diff --git a/servers/slapd/connection.c b/servers/slapd/connection.c index 252570efcf..71d6a35b57 100644 --- a/servers/slapd/connection.c +++ b/servers/slapd/connection.c @@ -620,7 +620,7 @@ long connection_init( LDAP_STAILQ_INIT(&c->c_pending_ops); #ifdef LDAP_X_TXN - c->c_txn = 0; + c->c_txn = CONN_TXN_INACTIVE; c->c_txn_backend = NULL; LDAP_STAILQ_INIT(&c->c_txn_ops); #endif @@ -667,7 +667,7 @@ long connection_init( assert( LDAP_STAILQ_EMPTY(&c->c_ops) ); assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) ); #ifdef LDAP_X_TXN - assert( c->c_txn == 0 ); + assert( c->c_txn == CONN_TXN_INACTIVE ); assert( c->c_txn_backend == NULL ); assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) ); #endif @@ -830,6 +830,12 @@ connection_destroy( Connection *c ) assert( c->c_struct_state != SLAP_C_UNUSED ); assert( c->c_conn_state != SLAP_C_INVALID ); assert( LDAP_STAILQ_EMPTY(&c->c_ops) ); + assert( LDAP_STAILQ_EMPTY(&c->c_pending_ops) ); +#ifdef LDAP_X_TXN + assert( c->c_txn == CONN_TXN_INACTIVE ); + assert( c->c_txn_backend == NULL ); + assert( LDAP_STAILQ_EMPTY(&c->c_txn_ops) ); +#endif assert( c->c_writewaiter == 0); /* only for stats (print -1 as "%lu" may give unexpected results ;) */ @@ -928,6 +934,7 @@ static void connection_abandon( Connection *c ) op.o_conn = c; op.o_connid = c->c_connid; op.o_tag = LDAP_REQ_ABANDON; + for ( o = LDAP_STAILQ_FIRST( &c->c_ops ); o; o=next ) { next = LDAP_STAILQ_NEXT( o, o_next ); op.orn_msgid = o->o_msgid; @@ -936,6 +943,19 @@ static void connection_abandon( Connection *c ) frontendDB->be_abandon( &op, &rs ); } +#ifdef LDAP_X_TXN + /* remove operations in pending transaction */ + while ( (o = LDAP_STAILQ_FIRST( &c->c_txn_ops )) != NULL) { + LDAP_STAILQ_REMOVE_HEAD( &c->c_txn_ops, o_next ); + LDAP_STAILQ_NEXT(o, o_next) = NULL; + slap_op_free( o ); + } + + /* clear transaction */ + c->c_txn_backend = NULL; + c->c_txn = CONN_TXN_INACTIVE; +#endif + /* remove pending operations */ while ( (o = LDAP_STAILQ_FIRST( &c->c_pending_ops )) != NULL) { LDAP_STAILQ_REMOVE_HEAD( &c->c_pending_ops, o_next ); @@ -978,6 +998,7 @@ void connection_closing( Connection *c, const char *why ) ldap_pvt_thread_yield(); ldap_pvt_thread_mutex_lock( &c->c_mutex ); } + } else if( why == NULL && c->c_close_reason == conn_lost_str ) { /* Client closed connection after doing Unbind. */ c->c_close_reason = NULL; diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 51d5ae3a9f..d1529f9d75 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -2449,7 +2449,6 @@ typedef struct slap_op { #define SLAP_CONTROL_DATA2 0x40 #define SLAP_CONTROL_DATA3 0x80 - #define _SCM(x) ((x) & SLAP_CONTROL_MASK) char o_ctrlflag[SLAP_MAX_CIDS]; /* per-control flags */ @@ -2521,9 +2520,9 @@ typedef struct slap_op { void *o_private; /* anything the backend needs */ - LDAP_STAILQ_ENTRY(slap_op) o_next; /* next operation in list */ - + LDAP_STAILQ_ENTRY(slap_op) o_next; /* next operation in list */ } Operation; + #define OPERATION_BUFFER_SIZE ( sizeof(Operation) + sizeof(Opheader) + \ SLAP_MAX_CIDS*sizeof(void *) ) @@ -2635,7 +2634,11 @@ typedef struct slap_conn { struct slap_op *c_sasl_bindop; /* set to current op if it's a bind */ #ifdef LDAP_X_TXN - int c_txn; /* true if transaction started */ +#define CONN_TXN_INACTIVE 0 +#define CONN_TXN_SPECIFY 1 +#define CONN_TXN_SETTLE -1 + int c_txn; + Backend *c_txn_backend; LDAP_STAILQ_HEAD(c_to, slap_op) c_txn_ops; /* list of operations in txn */ #endif diff --git a/servers/slapd/txn.c b/servers/slapd/txn.c index c86cd12ca8..b087a35463 100644 --- a/servers/slapd/txn.c +++ b/servers/slapd/txn.c @@ -56,14 +56,14 @@ int txn_start_extop( /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - if( op->o_conn->c_txn ) { + if( op->o_conn->c_txn != CONN_TXN_INACTIVE ) { rs->sr_text = "Too many transactions"; rc = LDAP_BUSY; goto done; } assert( op->o_conn->c_txn_backend == NULL ); - ++op->o_conn->c_txn; + op->o_conn->c_txn = CONN_TXN_SPECIFY; bv = (struct berval *) ch_malloc( sizeof (struct berval) ); bv->bv_len = 0; @@ -173,13 +173,24 @@ int txn_end_extop( /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); - if( op->o_conn->c_txn == 0 ) { + if( op->o_conn->c_txn != CONN_TXN_SPECIFY ) { rs->sr_text = "invalid transaction identifier"; rc = LDAP_X_TXN_ID_INVALID; goto done; } + op->o_conn->c_txn = CONN_TXN_SETTLE; if( commit ) { + if ( op->o_abandon ) { + } + + if( LDAP_STAILQ_EMPTY(&op->o_conn->c_txn_ops) ) { + /* no updates to commit */ + rs->sr_text = "no updates to commit"; + rc = LDAP_OPERATIONS_ERROR; + goto settled; + } + rs->sr_text = "not yet implemented"; rc = LDAP_UNWILLING_TO_PERFORM; @@ -188,7 +199,13 @@ int txn_end_extop( rc = LDAP_SUCCESS;; } - op->o_conn->c_txn = 0; +drain: + /* drain txn ops list */ + +settled: + assert( LDAP_STAILQ_EMPTY(&op->o_conn->c_txn_ops) ); + assert( op->o_conn->c_txn == CONN_TXN_SETTLE ); + op->o_conn->c_txn = CONN_TXN_INACTIVE; op->o_conn->c_txn_backend = NULL; done: -- 2.39.5