r13818: Make ldb_tdb 'fake' async.
[jelmer/samba4-debian.git] / source / lib / ldb / ldb_tdb / ldb_tdb.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5    Copyright (C) Stefan Metzmacher  2004
6    Copyright (C) Simo Sorce       2006
7    
8
9      ** NOTE! The following LGPL license applies to the ldb
10      ** library. This does NOT imply that all of Samba is released
11      ** under the LGPL
12    
13    This library is free software; you can redistribute it and/or
14    modify it under the terms of the GNU Lesser General Public
15    License as published by the Free Software Foundation; either
16    version 2 of the License, or (at your option) any later version.
17
18    This library is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21    Lesser General Public License for more details.
22
23    You should have received a copy of the GNU Lesser General Public
24    License along with this library; if not, write to the Free Software
25    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 */
27
28 /*
29  *  Name: ldb_tdb
30  *
31  *  Component: ldb tdb backend
32  *
33  *  Description: core functions for tdb backend
34  *
35  *  Author: Andrew Tridgell
36  *  Author: Stefan Metzmacher
37  *
38  *  Modifications:
39  *
40  *  - description: make the module use asyncronous calls
41  *    date: Feb 2006
42  *    Author: Simo Sorce
43  */
44
45 #include "includes.h"
46 #include "ldb/include/includes.h"
47
48 #include "ldb/ldb_tdb/ldb_tdb.h"
49
50
51 /*
52   map a tdb error code to a ldb error code
53 */
54 static int ltdb_err_map(enum TDB_ERROR tdb_code)
55 {
56         switch (tdb_code) {
57         case TDB_SUCCESS:
58                 return LDB_SUCCESS;
59         case TDB_ERR_CORRUPT:
60         case TDB_ERR_OOM:
61         case TDB_ERR_EINVAL:
62                 return LDB_ERR_OPERATIONS_ERROR;
63         case TDB_ERR_IO:
64                 return LDB_ERR_PROTOCOL_ERROR;
65         case TDB_ERR_LOCK:
66         case TDB_ERR_NOLOCK:
67                 return LDB_ERR_BUSY;
68         case TDB_ERR_LOCK_TIMEOUT:
69                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
70         case TDB_ERR_EXISTS:
71                 return LDB_ERR_ENTRY_ALREADY_EXISTS;
72         case TDB_ERR_NOEXIST:
73                 return LDB_ERR_NO_SUCH_OBJECT;
74         case TDB_ERR_RDONLY:
75                 return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
76         }
77         return LDB_ERR_OTHER;
78 }
79
80
81 struct ldb_async_handle *init_ltdb_handle(struct ltdb_private *ltdb, struct ldb_module *module,
82                                           void *context,
83                                           int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
84                                           int timeout)
85 {
86         struct ltdb_async_context *ac;
87         struct ldb_async_handle *h;
88
89         h = talloc_zero(ltdb, struct ldb_async_handle);
90         if (h == NULL) {
91                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
92                 return NULL;
93         }
94
95         ac = talloc_zero(h, struct ltdb_async_context);
96         if (ac == NULL) {
97                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
98                 talloc_free(h);
99                 return NULL;
100         }
101
102         h->private_data = (void *)ac;
103
104         ac->module = module;
105         ac->context = context;
106         ac->callback = callback;
107         ac->timeout = timeout;
108
109         return h;
110 }
111
112 /*
113   form a TDB_DATA for a record key
114   caller frees
115
116   note that the key for a record can depend on whether the 
117   dn refers to a case sensitive index record or not
118 */
119 struct TDB_DATA ltdb_key(struct ldb_module *module, const struct ldb_dn *dn)
120 {
121         struct ldb_context *ldb = module->ldb;
122         TDB_DATA key;
123         char *key_str = NULL;
124         char *dn_folded = NULL;
125
126         /*
127           most DNs are case insensitive. The exception is index DNs for
128           case sensitive attributes
129
130           there are 3 cases dealt with in this code:
131
132           1) if the dn doesn't start with @ then uppercase the attribute
133              names and the attributes values of case insensitive attributes
134           2) if the dn starts with @ then leave it alone - the indexing code handles
135              the rest
136         */
137
138         dn_folded = ldb_dn_linearize_casefold(ldb, dn);
139         if (!dn_folded) {
140                 goto failed;
141         }
142
143         key_str = talloc_asprintf(ldb, "DN=%s", dn_folded);
144
145         talloc_free(dn_folded);
146
147         if (!key_str) {
148                 goto failed;
149         }
150
151         key.dptr = (uint8_t *)key_str;
152         key.dsize = strlen(key_str) + 1;
153
154         return key;
155
156 failed:
157         errno = ENOMEM;
158         key.dptr = NULL;
159         key.dsize = 0;
160         return key;
161 }
162
163 /*
164   check special dn's have valid attributes
165   currently only @ATTRIBUTES is checked
166 */
167 int ltdb_check_special_dn(struct ldb_module *module, const struct ldb_message *msg)
168 {
169         int i, j;
170  
171         if (! ldb_dn_is_special(msg->dn) ||
172             ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
173                 return 0;
174         }
175
176         /* we have @ATTRIBUTES, let's check attributes are fine */
177         /* should we check that we deny multivalued attributes ? */
178         for (i = 0; i < msg->num_elements; i++) {
179                 for (j = 0; j < msg->elements[i].num_values; j++) {
180                         if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
181                                 char *err_string = talloc_strdup(module, "Invalid attribute value in an @ATTRIBUTES entry");
182                                 if (err_string) {
183                                         ldb_set_errstring(module->ldb, err_string);
184                                 }
185                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
186                         }
187                 }
188         }
189
190         return 0;
191 }
192
193
194 /*
195   we've made a modification to a dn - possibly reindex and 
196   update sequence number
197 */
198 static int ltdb_modified(struct ldb_module *module, const struct ldb_dn *dn)
199 {
200         int ret = 0;
201
202         if (ldb_dn_is_special(dn) &&
203             (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
204              ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) ) {
205                 ret = ltdb_reindex(module);
206         }
207
208         if (ret == 0 &&
209             !(ldb_dn_is_special(dn) &&
210               ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
211                 ret = ltdb_increase_sequence_number(module);
212         }
213
214         return ret;
215 }
216
217 /*
218   store a record into the db
219 */
220 int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs)
221 {
222         struct ltdb_private *ltdb = module->private_data;
223         TDB_DATA tdb_key, tdb_data;
224         int ret;
225
226         tdb_key = ltdb_key(module, msg->dn);
227         if (!tdb_key.dptr) {
228                 return LDB_ERR_OTHER;
229         }
230
231         ret = ltdb_pack_data(module, msg, &tdb_data);
232         if (ret == -1) {
233                 talloc_free(tdb_key.dptr);
234                 return LDB_ERR_OTHER;
235         }
236
237         ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
238         if (ret == -1) {
239                 ret = ltdb_err_map(tdb_error(ltdb->tdb));
240                 goto done;
241         }
242         
243         ret = ltdb_index_add(module, msg);
244         if (ret == -1) {
245                 tdb_delete(ltdb->tdb, tdb_key);
246         }
247
248 done:
249         talloc_free(tdb_key.dptr);
250         talloc_free(tdb_data.dptr);
251
252         return ret;
253 }
254
255
256 /*
257   add a record to the database
258 */
259 static int ltdb_add_async(struct ldb_module *module, const struct ldb_message *msg,
260                           void *context,
261                           int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
262                           int timeout,
263                           struct ldb_async_handle **handle)
264 {
265         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
266         struct ltdb_async_context *ltdb_ac;
267         int ret = LDB_ERR_OPERATIONS_ERROR;
268
269         *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
270         if (*handle == NULL) {
271                 return ret;
272         }
273         ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
274         (*handle)->state = LDB_ASYNC_DONE;
275         (*handle)->status = LDB_SUCCESS;
276
277         ret = ltdb_check_special_dn(module, msg);
278         if (ret != LDB_SUCCESS) {
279                 talloc_free(*handle);
280                 return ret;
281         }
282         
283         if (ltdb_cache_load(module) != 0) {
284                 talloc_free(*handle);
285                 return LDB_ERR_OTHER;
286         }
287
288         ret = ltdb_store(module, msg, TDB_INSERT);
289
290         if (ret != LDB_SUCCESS) {
291                 (*handle)->status = ret;
292                 return LDB_SUCCESS;
293         }
294
295         ltdb_modified(module, msg->dn);
296
297         if (ltdb_ac->callback)
298                 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
299         
300         return LDB_SUCCESS;
301 }
302
303 static int ltdb_add(struct ldb_module *module, const struct ldb_message *msg)
304 {
305         struct ldb_async_handle *handle;
306         int ret;
307
308         ret = ltdb_add_async(module, msg, NULL, NULL, 0, &handle);
309
310         if (ret != LDB_SUCCESS)
311                 return ret;
312
313         ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
314
315         talloc_free(handle);
316         return ret;
317 }
318
319 /*
320   delete a record from the database, not updating indexes (used for deleting
321   index records)
322 */
323 int ltdb_delete_noindex(struct ldb_module *module, const struct ldb_dn *dn)
324 {
325         struct ltdb_private *ltdb = module->private_data;
326         TDB_DATA tdb_key;
327         int ret;
328
329         tdb_key = ltdb_key(module, dn);
330         if (!tdb_key.dptr) {
331                 return LDB_ERR_OTHER;
332         }
333
334         ret = tdb_delete(ltdb->tdb, tdb_key);
335         talloc_free(tdb_key.dptr);
336
337         if (ret != 0) {
338                 ret = ltdb_err_map(tdb_error(ltdb->tdb));
339         }
340
341         return ret;
342 }
343
344 /*
345   delete a record from the database
346 */
347 static int ltdb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
348                              void *context,
349                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
350                              int timeout,
351                              struct ldb_async_handle **handle)
352 {
353         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
354         struct ltdb_async_context *ltdb_ac;
355         struct ldb_message *msg;
356         int ret = LDB_ERR_OPERATIONS_ERROR;
357
358         *handle = NULL;
359
360         if (ltdb_cache_load(module) != 0) {
361                 goto failed;
362         }
363
364         *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
365         if (*handle == NULL) {
366                 goto failed;
367         }
368         ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
369         (*handle)->state = LDB_ASYNC_DONE;
370         (*handle)->status = LDB_SUCCESS;
371
372         msg = talloc(ltdb_ac, struct ldb_message);
373         if (msg == NULL) {
374                 goto failed;
375         }
376
377         /* in case any attribute of the message was indexed, we need
378            to fetch the old record */
379         ret = ltdb_search_dn1(module, dn, msg);
380         if (ret != 1) {
381                 /* not finding the old record is an error */
382                 (*handle)->status = LDB_ERR_NO_SUCH_OBJECT;
383                 return LDB_SUCCESS;
384         }
385
386         ret = ltdb_delete_noindex(module, dn);
387         if (ret != LDB_SUCCESS) {
388                 goto failed;
389         }
390
391         /* remove any indexed attributes */
392         ret = ltdb_index_del(module, msg);
393         if (ret) {
394                 goto failed;
395         }
396         ltdb_modified(module, dn);
397
398         if (ltdb_ac->callback)
399                 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
400         
401         return LDB_SUCCESS;
402
403 failed:
404         talloc_free(*handle);
405         return ret;
406 }
407
408 static int ltdb_delete(struct ldb_module *module, const struct ldb_dn *dn)
409 {
410         struct ldb_async_handle *handle;
411         int ret;
412
413         ret = ltdb_delete_async(module, dn,
414                                 NULL, NULL, 0, &handle);
415
416         if (ret != LDB_SUCCESS)
417                 return ret;
418
419         ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
420
421         talloc_free(handle);
422         return ret;
423 }
424
425
426 /*
427   find an element by attribute name. At the moment this does a linear search, it should
428   be re-coded to use a binary search once all places that modify records guarantee
429   sorted order
430
431   return the index of the first matching element if found, otherwise -1
432 */
433 static int find_element(const struct ldb_message *msg, const char *name)
434 {
435         unsigned int i;
436         for (i=0;i<msg->num_elements;i++) {
437                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
438                         return i;
439                 }
440         }
441         return -1;
442 }
443
444
445 /*
446   add an element to an existing record. Assumes a elements array that we
447   can call re-alloc on, and assumed that we can re-use the data pointers from the 
448   passed in additional values. Use with care!
449
450   returns 0 on success, -1 on failure (and sets errno)
451 */
452 static int msg_add_element(struct ldb_context *ldb,
453                            struct ldb_message *msg, struct ldb_message_element *el)
454 {
455         struct ldb_message_element *e2;
456         unsigned int i;
457
458         e2 = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
459                               msg->num_elements+1);
460         if (!e2) {
461                 errno = ENOMEM;
462                 return -1;
463         }
464
465         msg->elements = e2;
466
467         e2 = &msg->elements[msg->num_elements];
468
469         e2->name = el->name;
470         e2->flags = el->flags;
471         e2->values = NULL;
472         if (el->num_values != 0) {
473                 e2->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
474                 if (!e2->values) {
475                         errno = ENOMEM;
476                         return -1;
477                 }
478         }
479         for (i=0;i<el->num_values;i++) {
480                 e2->values[i] = el->values[i];
481         }
482         e2->num_values = el->num_values;
483
484         msg->num_elements++;
485
486         return 0;
487 }
488
489 /*
490   delete all elements having a specified attribute name
491 */
492 static int msg_delete_attribute(struct ldb_module *module,
493                                 struct ldb_context *ldb,
494                                 struct ldb_message *msg, const char *name)
495 {
496         char *dn;
497         unsigned int i, j;
498
499         dn = ldb_dn_linearize(ldb, msg->dn);
500         if (dn == NULL) {
501                 return -1;
502         }
503
504         for (i=0;i<msg->num_elements;i++) {
505                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
506                         for (j=0;j<msg->elements[i].num_values;j++) {
507                                 ltdb_index_del_value(module, dn, &msg->elements[i], j);
508                         }
509                         talloc_free(msg->elements[i].values);
510                         if (msg->num_elements > (i+1)) {
511                                 memmove(&msg->elements[i], 
512                                         &msg->elements[i+1], 
513                                         sizeof(struct ldb_message_element)*
514                                         (msg->num_elements - (i+1)));
515                         }
516                         msg->num_elements--;
517                         i--;
518                         msg->elements = talloc_realloc(msg, msg->elements, 
519                                                          struct ldb_message_element, 
520                                                          msg->num_elements);
521                 }
522         }
523
524         talloc_free(dn);
525         return 0;
526 }
527
528 /*
529   delete all elements matching an attribute name/value 
530
531   return 0 on success, -1 on failure
532 */
533 static int msg_delete_element(struct ldb_module *module,
534                               struct ldb_message *msg, 
535                               const char *name,
536                               const struct ldb_val *val)
537 {
538         struct ldb_context *ldb = module->ldb;
539         unsigned int i;
540         int found;
541         struct ldb_message_element *el;
542         const struct ldb_attrib_handler *h;
543
544         found = find_element(msg, name);
545         if (found == -1) {
546                 return -1;
547         }
548
549         el = &msg->elements[found];
550
551         h = ldb_attrib_handler(ldb, el->name);
552
553         for (i=0;i<el->num_values;i++) {
554                 if (h->comparison_fn(ldb, ldb, &el->values[i], val) == 0) {
555                         if (i<el->num_values-1) {
556                                 memmove(&el->values[i], &el->values[i+1],
557                                         sizeof(el->values[i])*(el->num_values-(i+1)));
558                         }
559                         el->num_values--;
560                         if (el->num_values == 0) {
561                                 return msg_delete_attribute(module, ldb, msg, name);
562                         }
563                         return 0;
564                 }
565         }
566
567         return -1;
568 }
569
570
571 /*
572   modify a record - internal interface
573
574   yuck - this is O(n^2). Luckily n is usually small so we probably
575   get away with it, but if we ever have really large attribute lists 
576   then we'll need to look at this again
577 */
578 int ltdb_modify_internal(struct ldb_module *module, const struct ldb_message *msg)
579 {
580         struct ldb_context *ldb = module->ldb;
581         struct ltdb_private *ltdb = module->private_data;
582         TDB_DATA tdb_key, tdb_data;
583         struct ldb_message *msg2;
584         unsigned i, j;
585         int ret;
586
587         tdb_key = ltdb_key(module, msg->dn);
588         if (!tdb_key.dptr) {
589                 return LDB_ERR_OTHER;
590         }
591
592         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
593         if (!tdb_data.dptr) {
594                 talloc_free(tdb_key.dptr);
595                 return ltdb_err_map(tdb_error(ltdb->tdb));
596         }
597
598         msg2 = talloc(tdb_key.dptr, struct ldb_message);
599         if (msg2 == NULL) {
600                 talloc_free(tdb_key.dptr);
601                 return LDB_ERR_OTHER;
602         }
603
604         ret = ltdb_unpack_data(module, &tdb_data, msg2);
605         if (ret == -1) {
606                 talloc_free(tdb_key.dptr);
607                 free(tdb_data.dptr);
608                 return LDB_ERR_OTHER;
609         }
610
611         if (!msg2->dn) {
612                 msg2->dn = msg->dn;
613         }
614
615         for (i=0;i<msg->num_elements;i++) {
616                 struct ldb_message_element *el = &msg->elements[i];
617                 struct ldb_message_element *el2;
618                 struct ldb_val *vals;
619                 char *err_string;
620                 char *dn;
621
622                 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
623
624                 case LDB_FLAG_MOD_ADD:
625                         /* add this element to the message. fail if it
626                            already exists */
627                         ret = find_element(msg2, el->name);
628
629                         if (ret == -1) {
630                                 if (msg_add_element(ldb, msg2, el) != 0) {
631                                         ret = LDB_ERR_OTHER;
632                                         goto failed;
633                                 }
634                                 continue;
635                         }
636
637                         el2 = &msg2->elements[ret];
638
639                         /* An attribute with this name already exists, add all
640                          * values if they don't already exist. */
641
642                         for (j=0;j<el->num_values;j++) {
643                                 if (ldb_msg_find_val(el2, &el->values[j])) {
644                                         err_string = talloc_strdup(module, "Type or value exists");
645                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
646                                         ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
647                                         goto failed;
648                                 }
649                         }
650
651                         vals = talloc_realloc(msg2->elements, el2->values, struct ldb_val,
652                                                 el2->num_values + el->num_values);
653
654                         if (vals == NULL)
655                                 goto failed;
656
657                         for (j=0;j<el->num_values;j++) {
658                                 vals[el2->num_values + j] =
659                                         ldb_val_dup(vals, &el->values[j]);
660                         }
661
662                         el2->values = vals;
663                         el2->num_values += el->num_values;
664
665                         break;
666
667                 case LDB_FLAG_MOD_REPLACE:
668                         /* replace all elements of this attribute name with the elements
669                            listed. The attribute not existing is not an error */
670                         msg_delete_attribute(module, ldb, msg2, msg->elements[i].name);
671
672                         /* add the replacement element, if not empty */
673                         if (msg->elements[i].num_values != 0 &&
674                             msg_add_element(ldb, msg2, &msg->elements[i]) != 0) {
675                                 goto failed;
676                         }
677                         break;
678
679                 case LDB_FLAG_MOD_DELETE:
680
681                         dn = ldb_dn_linearize(msg2, msg->dn);
682                         if (dn == NULL) goto failed;
683
684                         /* we could be being asked to delete all
685                            values or just some values */
686                         if (msg->elements[i].num_values == 0) {
687                                 if (msg_delete_attribute(module, ldb, msg2, 
688                                                          msg->elements[i].name) != 0) {
689                                         err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
690                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
691                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
692                                         goto failed;
693                                 }
694                                 break;
695                         }
696                         for (j=0;j<msg->elements[i].num_values;j++) {
697                                 if (msg_delete_element(module,
698                                                        msg2, 
699                                                        msg->elements[i].name,
700                                                        &msg->elements[i].values[j]) != 0) {
701                                         err_string = talloc_asprintf(module, "No such attribute: %s", msg->elements[i].name);
702                                         if (err_string) ldb_set_errstring(module->ldb, err_string);
703                                         ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
704                                         goto failed;
705                                 }
706                                 if (ltdb_index_del_value(module, dn, &msg->elements[i], j) != 0) {
707                                         goto failed;
708                                 }
709                         }
710                         break;
711                 default:
712                         err_string = talloc_asprintf(module, "Invalid ldb_modify flags on %s: 0x%x", 
713                                                      msg->elements[i].name, 
714                                                      msg->elements[i].flags & LDB_FLAG_MOD_MASK);
715                         if (err_string) ldb_set_errstring(module->ldb, err_string);
716                         ret = LDB_ERR_PROTOCOL_ERROR;
717                         goto failed;
718                 }
719         }
720
721         /* we've made all the mods - save the modified record back into the database */
722         ret = ltdb_store(module, msg2, TDB_MODIFY);
723
724         talloc_free(tdb_key.dptr);
725         free(tdb_data.dptr);
726         return ret;
727
728 failed:
729         talloc_free(tdb_key.dptr);
730         free(tdb_data.dptr);
731         return ret;
732 }
733
734 /*
735   modify a record
736 */
737 static int ltdb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
738                           void *context,
739                           int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
740                           int timeout,
741                           struct ldb_async_handle **handle)
742 {
743         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
744         struct ltdb_async_context *ltdb_ac;
745         int ret = LDB_ERR_OPERATIONS_ERROR;
746
747         *handle = NULL;
748
749         *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
750         if (*handle == NULL) {
751                 return ret;
752         }
753         ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
754         (*handle)->state = LDB_ASYNC_DONE;
755         (*handle)->status = LDB_SUCCESS;
756
757         ret = ltdb_check_special_dn(module, msg);
758         if (ret != LDB_SUCCESS) {
759                 talloc_free(*handle);
760                 return ret;
761         }
762         
763         if (ltdb_cache_load(module) != 0) {
764                 talloc_free(*handle);
765                 return LDB_ERR_OTHER;
766         }
767
768         ret = ltdb_modify_internal(module, msg);
769
770         if (ret != LDB_SUCCESS) {
771                 (*handle)->status = ret;
772                 return LDB_SUCCESS;
773         }
774
775         ltdb_modified(module, msg->dn);
776
777         if (ltdb_ac->callback)
778                 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
779         
780         return LDB_SUCCESS;
781 }
782
783 static int ltdb_modify(struct ldb_module *module, const struct ldb_message *msg)
784 {
785         struct ldb_async_handle *handle;
786         int ret;
787
788         ret = ltdb_modify_async(module, msg, NULL, NULL, 0, &handle);
789
790         if (ret != LDB_SUCCESS)
791                 return ret;
792
793         ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
794
795         talloc_free(handle);
796         return ret;
797 }
798
799 /*
800   rename a record
801 */
802 static int ltdb_rename_async(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn,
803                              void *context,
804                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
805                              int timeout,
806                              struct ldb_async_handle **handle)
807 {
808         struct ltdb_private *ltdb = talloc_get_type(module->private_data, struct ltdb_private);
809         struct ltdb_async_context *ltdb_ac;
810         struct ldb_message *msg;
811         int ret = LDB_ERR_OPERATIONS_ERROR;
812
813         *handle = NULL;
814
815         if (ltdb_cache_load(module) != 0) {
816                 return ret;
817         }
818
819         *handle = init_ltdb_handle(ltdb, module, context, callback, timeout);
820         if (*handle == NULL) {
821                 goto failed;
822         }
823         ltdb_ac = talloc_get_type((*handle)->private_data, struct ltdb_async_context);
824         (*handle)->state = LDB_ASYNC_DONE;
825         (*handle)->status = LDB_SUCCESS;
826
827         msg = talloc(ltdb_ac, struct ldb_message);
828         if (msg == NULL) {
829                 goto failed;
830         }
831
832         /* in case any attribute of the message was indexed, we need
833            to fetch the old record */
834         ret = ltdb_search_dn1(module, olddn, msg);
835         if (ret != 1) {
836                 /* not finding the old record is an error */
837                 (*handle)->status = LDB_ERR_NO_SUCH_OBJECT;
838                 return LDB_SUCCESS;
839         }
840
841         msg->dn = ldb_dn_copy(msg, newdn);
842         if (!msg->dn) {
843                 ret = LDB_ERR_OPERATIONS_ERROR;
844                 goto failed;
845         }
846
847         ret = ltdb_add(module, msg);
848         if (ret != LDB_SUCCESS) {
849                 (*handle)->status = LDB_ERR_OPERATIONS_ERROR;
850                 return LDB_SUCCESS;
851         }
852
853         ret = ltdb_delete(module, olddn);
854         if (ret != LDB_SUCCESS) {
855                 ltdb_delete(module, newdn);
856                 (*handle)->status = ret;
857                 return LDB_SUCCESS;
858         }
859
860         if (ltdb_ac->callback)
861                 (*handle)->status = ltdb_ac->callback(module->ldb, ltdb_ac->context, NULL);
862
863         return LDB_SUCCESS;
864
865 failed:
866         talloc_free(*handle);
867         return ret;
868 }
869
870 static int ltdb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
871 {
872         struct ldb_async_handle *handle;
873         int ret;
874
875         ret = ltdb_rename_async(module, olddn, newdn,
876                                 NULL, NULL, 0, &handle);
877
878         if (ret != LDB_SUCCESS)
879                 return ret;
880
881         ret = ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
882
883         talloc_free(handle);
884         return ret;
885 }
886
887 static int ltdb_start_trans(struct ldb_module *module)
888 {
889         struct ltdb_private *ltdb = module->private_data;
890
891         if (tdb_transaction_start(ltdb->tdb) != 0) {
892                 return ltdb_err_map(tdb_error(ltdb->tdb));
893         }
894
895         return LDB_SUCCESS;
896 }
897
898 static int ltdb_end_trans(struct ldb_module *module)
899 {
900         struct ltdb_private *ltdb = module->private_data;
901
902         if (tdb_transaction_commit(ltdb->tdb) != 0) {
903                 return ltdb_err_map(tdb_error(ltdb->tdb));
904         }
905
906         return LDB_SUCCESS;
907 }
908
909 static int ltdb_del_trans(struct ldb_module *module)
910 {
911         struct ltdb_private *ltdb = module->private_data;
912
913         if (tdb_transaction_cancel(ltdb->tdb) != 0) {
914                 return ltdb_err_map(tdb_error(ltdb->tdb));
915         }
916
917         return LDB_SUCCESS;
918 }
919
920 static int ltdb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
921 {
922         return handle->status;
923 }
924
925 static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
926 {
927         /* check for oustanding critical controls and return an error if found */
928
929         if (req->controls != NULL) {
930                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls should not reach the ldb_tdb backend!\n");
931         }
932
933         if (check_critical_controls(req->controls)) {
934                 return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
935         }
936         
937         switch (req->operation) {
938
939         case LDB_REQ_SEARCH:
940                 return ltdb_search_bytree(module,
941                                           req->op.search.base,
942                                           req->op.search.scope, 
943                                           req->op.search.tree, 
944                                           req->op.search.attrs,
945                                           &req->op.search.res);
946
947         case LDB_REQ_ADD:
948                 return ltdb_add(module, req->op.add.message);
949
950         case LDB_REQ_MODIFY:
951                 return ltdb_modify(module, req->op.mod.message);
952
953         case LDB_REQ_DELETE:
954                 return ltdb_delete(module, req->op.del.dn);
955
956         case LDB_REQ_RENAME:
957                 return ltdb_rename(module,
958                                         req->op.rename.olddn,
959                                         req->op.rename.newdn);
960
961         case LDB_ASYNC_SEARCH:
962                 return ltdb_search_async(module,
963                                         req->op.search.base,
964                                         req->op.search.scope, 
965                                         req->op.search.tree, 
966                                         req->op.search.attrs,
967                                         req->async.context,
968                                         req->async.callback,
969                                         req->async.timeout,
970                                         &req->async.handle);
971
972         case LDB_ASYNC_ADD:
973                 return ltdb_add_async(module,
974                                         req->op.add.message,
975                                         req->async.context,
976                                         req->async.callback,
977                                         req->async.timeout,
978                                         &req->async.handle);
979
980         case LDB_ASYNC_MODIFY:
981                 return ltdb_modify_async(module,
982                                         req->op.mod.message,
983                                         req->async.context,
984                                         req->async.callback,
985                                         req->async.timeout,
986                                         &req->async.handle);
987
988         case LDB_ASYNC_DELETE:
989                 return ltdb_delete_async(module,
990                                         req->op.del.dn,
991                                         req->async.context,
992                                         req->async.callback,
993                                         req->async.timeout,
994                                         &req->async.handle);
995
996         case LDB_ASYNC_RENAME:
997                 return ltdb_rename_async(module,
998                                         req->op.rename.olddn,
999                                         req->op.rename.newdn,
1000                                         req->async.context,
1001                                         req->async.callback,
1002                                         req->async.timeout,
1003                                         &req->async.handle);
1004
1005         default:
1006                 return LDB_ERR_OPERATIONS_ERROR;
1007
1008         }
1009 }
1010
1011 /*
1012   return sequenceNumber from @BASEINFO
1013 */
1014 static uint64_t ltdb_sequence_number(struct ldb_context *ldb)
1015 {
1016         TALLOC_CTX *tmp_ctx = talloc_new(ldb);
1017         const char *attrs[] = { "sequenceNumber", NULL };
1018         struct ldb_result *res = NULL;
1019         struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO");
1020         int ret;
1021         uint64_t seq_num;
1022
1023         ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
1024         talloc_steal(tmp_ctx, res);
1025         if (ret != LDB_SUCCESS || res->count != 1) {
1026                 talloc_free(tmp_ctx);
1027                 /* zero is as good as anything when we don't know */
1028                 return 0;
1029         }
1030
1031         seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0);
1032         talloc_free(tmp_ctx);
1033         return seq_num; 
1034 }
1035
1036 static const struct ldb_module_ops ltdb_ops = {
1037         .name              = "tdb",
1038         .request           = ltdb_request,
1039         .start_transaction = ltdb_start_trans,
1040         .end_transaction   = ltdb_end_trans,
1041         .del_transaction   = ltdb_del_trans
1042 };
1043
1044
1045 /*
1046   connect to the database
1047 */
1048 int ltdb_connect(struct ldb_context *ldb, const char *url, 
1049                  unsigned int flags, const char *options[])
1050 {
1051         const char *path;
1052         int tdb_flags, open_flags;
1053         struct ltdb_private *ltdb;
1054
1055         /* parse the url */
1056         if (strchr(url, ':')) {
1057                 if (strncmp(url, "tdb://", 6) != 0) {
1058                         ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid tdb URL '%s'", url);
1059                         return -1;
1060                 }
1061                 path = url+6;
1062         } else {
1063                 path = url;
1064         }
1065
1066         tdb_flags = TDB_DEFAULT;
1067
1068         /* check for the 'nosync' option */
1069         if (flags & LDB_FLG_NOSYNC) {
1070                 tdb_flags |= TDB_NOSYNC;
1071         }
1072
1073         if (flags & LDB_FLG_RDONLY) {
1074                 open_flags = O_RDONLY;
1075         } else {
1076                 open_flags = O_CREAT | O_RDWR;
1077         }
1078
1079         ltdb = talloc_zero(ldb, struct ltdb_private);
1080         if (!ltdb) {
1081                 ldb_oom(ldb);
1082                 return -1;
1083         }
1084
1085         /* note that we use quite a large default hash size */
1086         ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, tdb_flags, open_flags, 0666);
1087         if (!ltdb->tdb) {
1088                 ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path);
1089                 talloc_free(ltdb);
1090                 return -1;
1091         }
1092
1093         ltdb->sequence_number = 0;
1094
1095         ldb->modules = talloc(ldb, struct ldb_module);
1096         if (!ldb->modules) {
1097                 ldb_oom(ldb);
1098                 talloc_free(ltdb);
1099                 return -1;
1100         }
1101         ldb->modules->ldb = ldb;
1102         ldb->modules->prev = ldb->modules->next = NULL;
1103         ldb->modules->private_data = ltdb;
1104         ldb->modules->ops = &ltdb_ops;
1105         ldb->sequence_number = ltdb_sequence_number;
1106
1107         ldb->async_wait = &ltdb_async_wait;
1108
1109         return 0;
1110 }