]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb2/add.c
Make bdb2i_back_modify_internal() public so it can be reused from
[openldap] / servers / slapd / back-bdb2 / add.c
1 /* add.c - ldap bdb2 back-end add routine */
2
3 #include "portable.h"
4
5 #include <stdio.h>
6
7 #include <ac/socket.h>
8 #include <ac/string.h>
9
10 #include "slap.h"
11 #include "back-bdb2.h"
12 #include "proto-back-bdb2.h"
13
14 static DB_LOCK         lock;
15
16
17 static int
18 bdb2i_back_add_internal(
19     BackendDB   *be,
20     Connection  *conn,
21     Operation   *op,
22     Entry       *e
23 )
24 {
25         struct ldbminfo *li = (struct ldbminfo *) be->be_private;
26         char            *pdn;
27         Entry           *p = NULL;
28         int                     rc; 
29         struct timeval  time1;
30
31         Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_add: %s\n", e->e_dn, 0, 0);
32
33         if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
34                 entry_free( e );
35                 send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
36                 return( -1 );
37         }
38
39         if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
40                 Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
41                         0, 0, 0 );
42
43                 entry_free( e );
44                 send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
45                     "" );
46                 return( -1 );
47         }
48
49         /*
50          * Get the parent dn and see if the corresponding entry exists.
51          * If the parent does not exist, only allow the "root" user to
52          * add the entry.
53          */
54
55         if ( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
56                 char *matched = NULL;
57
58                 /* get parent with writer lock */
59                 if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
60                         Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
61                             0, 0 );
62                         send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
63                             matched, "" );
64
65                         if ( matched != NULL ) {
66                                 free( matched );
67                         }
68
69                         entry_free( e );
70                         free( pdn );
71                         return -1;
72                 }
73
74                 free(pdn);
75
76                 if ( matched != NULL ) {
77                         free( matched );
78                 }
79
80                 if ( ! access_allowed( be, conn, op, p,
81                         "children", NULL, ACL_WRITE ) )
82                 {
83                         Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
84                             0, 0 );
85                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
86                             "", "" );
87
88                         /* free parent and writer lock */
89                         bdb2i_cache_return_entry_w( &li->li_cache, p ); 
90
91                         entry_free( e );
92                         return -1;
93                 }
94
95         } else {
96                 /* no parent, must be adding entry to root */
97                 if ( ! be_isroot( be, op->o_ndn ) ) {
98                         Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0,
99                             0, 0 );
100                         send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
101                             "", "" );
102
103                         entry_free( e );
104                         return -1;
105                 }
106         }
107
108         e->e_id = bdb2i_next_id( be );
109
110         /*
111          * Try to add the entry to the cache, assign it a new dnid.
112          */
113         bdb2i_start_timing( be->bd_info, &time1 );
114
115         rc = bdb2i_cache_add_entry_rw( &li->li_cache, e, CACHE_WRITE_LOCK );
116
117         bdb2i_stop_timing( be->bd_info, time1, "ADD-CACHE", conn, op );
118
119         if ( rc != 0 ) {
120                 if( p != NULL) {
121                         /* free parent and writer lock */
122                         bdb2i_cache_return_entry_w( &li->li_cache, p ); 
123                 }
124
125                 Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
126                     0 );
127
128                 /* return the id */
129                 bdb2i_next_id_return( be, e->e_id );
130                 
131                 /* free the entry */
132                 entry_free( e );
133
134                 if(rc > 0) {
135                         send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
136                 } else {
137                         send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
138                 }
139
140                 return( -1 );
141         }
142
143         rc = -1;
144
145         /*
146          * add it to the id2children index for the parent
147          */
148
149         bdb2i_start_timing( be->bd_info, &time1 );
150
151         if ( bdb2i_id2children_add( be, p, e ) != 0 ) {
152                 Debug( LDAP_DEBUG_TRACE, "bdb2i_id2children_add failed\n", 0,
153                     0, 0 );
154                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
155
156                 bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
157
158                 goto return_results;
159         }
160
161         bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
162
163         /*
164          * Add the entry to the attribute indexes, then add it to
165          * the id2children index, dn2id index, and the id2entry index.
166          */
167
168         bdb2i_start_timing( be->bd_info, &time1 );
169
170         /* attribute indexes */
171         if ( bdb2i_index_add_entry( be, e ) != 0 ) {
172                 Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
173                     0, 0 );
174                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
175
176                 bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
177
178                 goto return_results;
179         }
180
181         bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
182
183         bdb2i_start_timing( be->bd_info, &time1 );
184
185         /* dn2id index */
186         if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
187                 Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
188                     0, 0 );
189                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
190
191                 bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
192
193                 goto return_results;
194         }
195
196         bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
197
198         bdb2i_start_timing( be->bd_info, &time1 );
199
200         /* id2entry index */
201         if ( bdb2i_id2entry_add( be, e ) != 0 ) {
202                 Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
203                     0, 0 );
204                 (void) bdb2i_dn2id_delete( be, e->e_ndn );
205                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
206
207                 bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
208
209                 goto return_results;
210         }
211
212         bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
213
214         send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
215         rc = 0;
216
217 return_results:;
218         if (p != NULL) {
219                 /* free parent and writer lock */
220                 bdb2i_cache_return_entry_w( &li->li_cache, p ); 
221         }
222
223         if ( rc ) {
224                 /* free entry and writer lock */
225                 bdb2i_cache_return_entry_w( &li->li_cache, e );
226         }
227
228         return( rc );
229 }
230
231
232 int
233 bdb2_back_add(
234     BackendDB   *be,
235     Connection  *conn,
236     Operation   *op,
237     Entry       *e
238 )
239 {
240         struct ldbminfo *li  = (struct ldbminfo *) be->be_private;
241         struct timeval  time1;
242         int             ret;
243
244         bdb2i_start_timing( be->bd_info, &time1 );
245
246         if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
247
248                 send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
249                 return( -1 );
250
251         }
252
253         /*  check, if a new default attribute index will be created,
254                 in which case we have to open the index file BEFORE TP  */
255         switch ( slapMode ) {
256                 case SLAP_SERVER_MODE:
257                 case SLAP_TIMEDSERVER_MODE:
258                 case SLAP_TOOL_MODE:
259                 case SLAP_TOOLID_MODE:
260                         bdb2i_check_default_attr_index_add( li, e );
261                         break;
262         }
263
264         ret = bdb2i_back_add_internal( be, conn, op, e );
265
266         /*  if the operation was successful, we will delay the unlock  */
267         if ( ret )
268                 (void) bdb2i_leave_backend_w( lock );
269
270         bdb2i_stop_timing( be->bd_info, time1, "ADD", conn, op );
271
272         return( ret );
273 }
274
275
276 int
277 bdb2i_release_add_lock( void )
278 {
279         (void) bdb2i_leave_backend_w( lock );
280         return 0;
281 }
282
283