]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/txn.c
apparently, structural_class() args changed
[openldap] / servers / slapd / txn.c
index e0d46670f07de77561870c6a2cdb24e1c7ff1643..b087a35463fdf7ead229d613a90b27a8c6e1537e 100644 (file)
@@ -35,16 +35,17 @@ const struct berval slap_EXOP_TXN_END = BER_BVC(LDAP_EXOP_X_TXN_END);
 int txn_start_extop(
        Operation *op, SlapReply *rs )
 {
+       int rc;
        struct berval *bv;
 
+       Statslog( LDAP_DEBUG_STATS, "%s TXN START\n",
+               op->o_log_prefix, 0, 0, 0, 0 );
+
        if( op->ore_reqdata != NULL ) {
                rs->sr_text = "no request data expected";
                return LDAP_PROTOCOL_ERROR;
        }
 
-       Statslog( LDAP_DEBUG_STATS, "%s TXN START\n",
-               op->o_log_prefix, 0, 0, 0, 0 );
-
        op->o_bd = op->o_conn->c_authz_backend;
        if( backend_check_restrictions( op, rs,
                (struct berval *)&slap_EXOP_TXN_START ) != LDAP_SUCCESS )
@@ -52,12 +53,29 @@ int txn_start_extop(
                return rs->sr_err;
        }
 
+       /* acquire connection lock */
+       ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
+
+       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 = CONN_TXN_SPECIFY;
+
        bv = (struct berval *) ch_malloc( sizeof (struct berval) );
        bv->bv_len = 0;
        bv->bv_val = NULL;
 
        rs->sr_rspdata = bv;
-       return LDAP_SUCCESS;
+       rc = LDAP_SUCCESS;
+
+done:
+       /* release connection lock */
+       ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
+       return rc;
 }
 
 int txn_spec_ctrl(
@@ -81,6 +99,15 @@ int txn_spec_ctrl(
                return LDAP_X_TXN_ID_INVALID;
        }
 
+       if ( op->o_preread ) { /* temporary limitation */
+               rs->sr_text = "cannot perform pre-read in transaction";
+               return LDAP_UNWILLING_TO_PERFORM;
+       } 
+       if ( op->o_postread ) { /* temporary limitation */
+               rs->sr_text = "cannot perform post-read in transaction";
+               return LDAP_UNWILLING_TO_PERFORM;
+       }
+
        op->o_txnSpec = SLAP_CONTROL_CRITICAL;
        return LDAP_SUCCESS;
 }
@@ -88,13 +115,25 @@ int txn_spec_ctrl(
 int txn_end_extop(
        Operation *op, SlapReply *rs )
 {
+       int rc;
+       BerElementBuffer berbuf;
+       BerElement *ber = (BerElement *)&berbuf;
+       ber_tag_t tag;
+       ber_len_t len;
+       ber_int_t commit=1;
+       struct berval txnid;
+
+       Statslog( LDAP_DEBUG_STATS, "%s TXN END\n",
+               op->o_log_prefix, 0, 0, 0, 0 );
+
        if( op->ore_reqdata == NULL ) {
                rs->sr_text = "request data expected";
                return LDAP_PROTOCOL_ERROR;
        }
-
-       Statslog( LDAP_DEBUG_STATS, "%s TXN END\n",
-               op->o_log_prefix, 0, 0, 0, 0 );
+       if( op->ore_reqdata->bv_len == 0 ) {
+               rs->sr_text = "empty request data";
+               return LDAP_PROTOCOL_ERROR;
+       }
 
        op->o_bd = op->o_conn->c_authz_backend;
        if( backend_check_restrictions( op, rs,
@@ -103,8 +142,77 @@ int txn_end_extop(
                return rs->sr_err;
        }
 
-       rs->sr_text = "not yet implemented";
-       return LDAP_UNWILLING_TO_PERFORM;
+       ber_init2( ber, op->ore_reqdata, 0 );
+
+       tag = ber_scanf( ber, "{" /*}*/ );
+       if( tag == LBER_ERROR ) {
+               rs->sr_text = "request data decoding error";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       tag = ber_peek_tag( ber, &len );
+       if( tag == LBER_BOOLEAN ) {
+               tag = ber_scanf( ber, "b", &commit );
+               if( tag == LBER_ERROR ) {
+                       rs->sr_text = "request data decoding error";
+                       return LDAP_PROTOCOL_ERROR;
+               }
+       }
+
+       tag = ber_scanf( ber, /*{*/ "m}", &txnid );
+       if( tag == LBER_ERROR ) {
+               rs->sr_text = "request data decoding error";
+               return LDAP_PROTOCOL_ERROR;
+       }
+
+       if( txnid.bv_len ) {
+               rs->sr_text = "invalid transaction identifier";
+               return LDAP_X_TXN_ID_INVALID;
+       }
+
+       /* acquire connection lock */
+       ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
+
+       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;
+
+       } else {
+               rs->sr_text = "transaction aborted";
+               rc = LDAP_SUCCESS;;
+       }
+
+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:
+       /* release connection lock */
+       ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
+
+       return rc;
 }
 
 #endif /* LDAP_X_TXN */