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);
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;
/* 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
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 );
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;
/* 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
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 );
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;
/* 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
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" );
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;
/* 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
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
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
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 ;) */
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;
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 );
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;
#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 */
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 *) )
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
/* 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;
/* 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;
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: