]> git.sur5r.net Git - openldap/blob - servers/slapd/txn.c
d1451c52d45d373903ea44a73ffa296513bfa881
[openldap] / servers / slapd / txn.c
1 /* txn.c - LDAP Transactions */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2006 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16
17 #include "portable.h"
18
19 #include <stdio.h>
20
21 #include <ac/krb.h>
22 #include <ac/socket.h>
23 #include <ac/string.h>
24 #include <ac/unistd.h>
25
26 #include "slap.h"
27
28 #include <lber_pvt.h>
29 #include <lutil.h>
30
31 #ifdef LDAP_X_TXN
32 const struct berval slap_EXOP_TXN_START = BER_BVC(LDAP_EXOP_X_TXN_START);
33 const struct berval slap_EXOP_TXN_END = BER_BVC(LDAP_EXOP_X_TXN_END);
34
35 int txn_start_extop(
36         Operation *op, SlapReply *rs )
37 {
38         int rc;
39         struct berval *bv;
40
41         Statslog( LDAP_DEBUG_STATS, "%s TXN START\n",
42                 op->o_log_prefix, 0, 0, 0, 0 );
43
44         if( op->ore_reqdata != NULL ) {
45                 rs->sr_text = "no request data expected";
46                 return LDAP_PROTOCOL_ERROR;
47         }
48
49         op->o_bd = op->o_conn->c_authz_backend;
50         if( backend_check_restrictions( op, rs,
51                 (struct berval *)&slap_EXOP_TXN_START ) != LDAP_SUCCESS )
52         {
53                 return rs->sr_err;
54         }
55
56         /* acquire connection lock */
57         ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
58
59         if( op->o_conn->c_txn ) {
60                 rs->sr_text = "Too many transactions";
61                 rc = LDAP_BUSY;
62                 goto done;
63         }
64
65         ++op->o_conn->c_txn;
66
67         bv = (struct berval *) ch_malloc( sizeof (struct berval) );
68         bv->bv_len = 0;
69         bv->bv_val = NULL;
70
71         rs->sr_rspdata = bv;
72         rc = LDAP_SUCCESS;
73
74 done:
75         /* release connection lock */
76         ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
77         return rc;
78 }
79
80 int txn_spec_ctrl(
81         Operation *op, SlapReply *rs, LDAPControl *ctrl )
82 {
83         if ( !ctrl->ldctl_iscritical ) {
84                 rs->sr_text = "txnSpec control must be marked critical";
85                 return LDAP_PROTOCOL_ERROR;
86         }
87         if( op->o_txnSpec ) {
88                 rs->sr_text = "txnSpec control provided multiple times";
89                 return LDAP_PROTOCOL_ERROR;
90         }
91
92         if ( ctrl->ldctl_value.bv_val == NULL ) {
93                 rs->sr_text = "no transaction identifier provided";
94                 return LDAP_PROTOCOL_ERROR;
95         }
96         if ( ctrl->ldctl_value.bv_len != 0 ) {
97                 rs->sr_text = "invalid transaction identifier";
98                 return LDAP_X_TXN_ID_INVALID;
99         }
100
101         op->o_txnSpec = SLAP_CONTROL_CRITICAL;
102         return LDAP_SUCCESS;
103 }
104
105 int txn_end_extop(
106         Operation *op, SlapReply *rs )
107 {
108         int rc;
109         BerElementBuffer berbuf;
110         BerElement *ber = (BerElement *)&berbuf;
111         ber_tag_t tag;
112         ber_len_t len;
113         ber_int_t commit=1;
114         struct berval txnid;
115
116         Statslog( LDAP_DEBUG_STATS, "%s TXN END\n",
117                 op->o_log_prefix, 0, 0, 0, 0 );
118
119         if( op->ore_reqdata == NULL ) {
120                 rs->sr_text = "request data expected";
121                 return LDAP_PROTOCOL_ERROR;
122         }
123         if( op->ore_reqdata->bv_len == 0 ) {
124                 rs->sr_text = "empty request data";
125                 return LDAP_PROTOCOL_ERROR;
126         }
127
128         op->o_bd = op->o_conn->c_authz_backend;
129         if( backend_check_restrictions( op, rs,
130                 (struct berval *)&slap_EXOP_TXN_END ) != LDAP_SUCCESS )
131         {
132                 return rs->sr_err;
133         }
134
135         ber_init2( ber, op->ore_reqdata, 0 );
136
137         tag = ber_scanf( ber, "{" /*}*/ );
138         if( tag == LBER_ERROR ) {
139                 rs->sr_text = "request data decoding error";
140                 return LDAP_PROTOCOL_ERROR;
141         }
142
143         tag = ber_peek_tag( ber, &len );
144         assert( tag == LBER_BOOLEAN );
145         if( tag == LBER_BOOLEAN ) {
146                 tag = ber_scanf( ber, "b", &commit );
147                 if( tag == LBER_ERROR ) {
148                         rs->sr_text = "request data decoding error";
149                         return LDAP_PROTOCOL_ERROR;
150                 }
151         }
152
153         tag = ber_scanf( ber, /*{*/ "m}", &txnid );
154         if( tag == LBER_ERROR ) {
155                 rs->sr_text = "request data decoding error";
156                 return LDAP_PROTOCOL_ERROR;
157         }
158
159         if( txnid.bv_len ) {
160                 rs->sr_text = "invalid transaction identifier";
161                 return LDAP_X_TXN_ID_INVALID;
162         }
163
164         /* acquire connection lock */
165         ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
166
167         if( op->o_conn->c_txn == 0 ) {
168                 rs->sr_text = "invalid transaction identifier";
169                 rc = LDAP_X_TXN_ID_INVALID;
170                 goto done;
171         }
172
173         if( commit ) {
174                 rs->sr_text = "not yet implemented";
175                 rc = LDAP_UNWILLING_TO_PERFORM;
176
177         } else {
178                 rs->sr_text = "transaction aborted";
179                 rc = LDAP_SUCCESS;;
180         }
181
182         op->o_conn->c_txn = 0;
183
184 done:
185         /* release connection lock */
186         ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
187
188         return rc;
189 }
190
191 #endif /* LDAP_X_TXN */