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