Commit 71511a05 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

more txn infrastructure

parent 3b4fc9b3
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment