r502: modified ldb to allow the use of an external pool memory
[jra/samba/.git] / source4 / lib / ldb / ldb_tdb / ldb_tdb.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5
6      ** NOTE! The following LGPL license applies to the ldb
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9    
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25 /*
26  *  Name: ldb
27  *
28  *  Component: ldb tdb backend
29  *
30  *  Description: core functions for tdb backend
31  *
32  *  Author: Andrew Tridgell
33  */
34
35 #include "includes.h"
36 #include "ldb/ldb_tdb/ldb_tdb.h"
37
38 /*
39   form a TDB_DATA for a record key
40   caller frees
41
42   note that the key for a record can depend on whether the 
43   dn refers to a case sensitive index record or not
44 */
45 struct TDB_DATA ltdb_key(struct ldb_context *ldb, const char *dn)
46 {
47         TDB_DATA key;
48         char *key_str = NULL;
49         char *dn_folded = NULL;
50         const char *prefix = LTDB_INDEX ":";
51         const char *s;
52         int flags;
53
54         /*
55           most DNs are case insensitive. The exception is index DNs for
56           case sensitive attributes
57
58           there are 3 cases dealt with in this code:
59
60           1) if the dn doesn't start with @INDEX: then uppercase whole dn
61           2) if the dn starts with @INDEX:attr and 'attr' is a case insensitive
62              attribute then uppercase whole dn
63           3) if the dn starts with @INDEX:attr and 'attr' is a case sensitive
64              attribute then uppercase up to the value of the attribute, but 
65              not the value itself
66         */
67         if (strncmp(dn, prefix, strlen(prefix)) == 0 &&
68             (s = strchr(dn+strlen(prefix), ':'))) {
69                 char *attr_name, *attr_name_folded;
70                 attr_name = ldb_strndup(ldb, dn+strlen(prefix), (s-(dn+strlen(prefix))));
71                 if (!attr_name) {
72                         goto failed;
73                 }
74                 flags = ltdb_attribute_flags(ldb, attr_name);
75                 
76                 if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
77                         dn_folded = ldb_casefold(ldb, dn);
78                 } else {
79                         attr_name_folded = ldb_casefold(ldb, attr_name);
80                         if (!attr_name_folded) {
81                                 goto failed;
82                         }
83                         ldb_asprintf(ldb, &dn_folded, "%s:%s:%s",
84                                  prefix, attr_name_folded,
85                                  s+1);
86                         ldb_free(ldb, attr_name_folded);
87                 }
88                 ldb_free(ldb, attr_name);
89         } else {
90                 dn_folded = ldb_casefold(ldb, dn);
91         }
92
93         if (!dn_folded) {
94                 goto failed;
95         }
96
97         ldb_asprintf(ldb, &key_str, "DN=%s", dn_folded);
98         ldb_free(ldb, dn_folded);
99
100         if (!key_str) {
101                 goto failed;
102         }
103
104         key.dptr = key_str;
105         key.dsize = strlen(key_str)+1;
106
107         return key;
108
109 failed:
110         errno = ENOMEM;
111         key.dptr = NULL;
112         key.dsize = 0;
113         return key;
114 }
115
116 /*
117   lock the database for write - currently a single lock is used
118 */
119 static int ltdb_lock(struct ldb_context *ldb)
120 {
121         struct ltdb_private *ltdb = ldb->private_data;
122         TDB_DATA key;
123         int ret;
124
125         key = ltdb_key(ldb, "LDBLOCK");
126         if (!key.dptr) {
127                 return -1;
128         }
129
130         ret = tdb_chainlock(ltdb->tdb, key);
131
132         ldb_free(ldb, key.dptr);
133
134         return ret;
135 }
136
137 /*
138   unlock the database after a ltdb_lock()
139 */
140 static void ltdb_unlock(struct ldb_context *ldb)
141 {
142         struct ltdb_private *ltdb = ldb->private_data;
143         TDB_DATA key;
144
145         key = ltdb_key(ldb, "LDBLOCK");
146         if (!key.dptr) {
147                 return;
148         }
149
150         tdb_chainunlock(ltdb->tdb, key);
151
152         ldb_free(ldb, key.dptr);
153 }
154
155
156 /*
157   we've made a modification to a dn - possibly reindex and 
158   update sequence number
159 */
160 static int ltdb_modified(struct ldb_context *ldb, const char *dn)
161 {
162         int ret = 0;
163
164         if (strcmp(dn, LTDB_INDEXLIST) == 0 ||
165             strcmp(dn, LTDB_ATTRIBUTES) == 0) {
166                 ret = ltdb_reindex(ldb);
167         }
168
169         if (ret == 0 &&
170             strcmp(dn, LTDB_BASEINFO) != 0) {
171                 ret = ltdb_increase_sequence_number(ldb);
172         }
173
174         return ret;
175 }
176
177 /*
178   store a record into the db
179 */
180 int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs)
181 {
182         struct ltdb_private *ltdb = ldb->private_data;
183         TDB_DATA tdb_key, tdb_data;
184         int ret;
185
186         tdb_key = ltdb_key(ldb, msg->dn);
187         if (!tdb_key.dptr) {
188                 return -1;
189         }
190
191         ret = ltdb_pack_data(ldb, msg, &tdb_data);
192         if (ret == -1) {
193                 ldb_free(ldb, tdb_key.dptr);
194                 return -1;
195         }
196
197         ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
198         if (ret == -1) {
199                 goto done;
200         }
201         
202         ret = ltdb_index_add(ldb, msg);
203         if (ret == -1) {
204                 tdb_delete(ltdb->tdb, tdb_key);
205         }
206
207 done:
208         ldb_free(ldb, tdb_key.dptr);
209         ldb_free(ldb, tdb_data.dptr);
210
211         return ret;
212 }
213
214
215 /*
216   add a record to the database
217 */
218 static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg)
219 {
220         struct ltdb_private *ltdb = ldb->private_data;
221         int ret;
222
223         ltdb->last_err_string = NULL;
224
225         if (ltdb_lock(ldb) != 0) {
226                 return -1;
227         }
228
229         if (ltdb_cache_load(ldb) != 0) {
230                 ltdb_unlock(ldb);
231                 return -1;
232         }
233         
234         ret = ltdb_store(ldb, msg, TDB_INSERT);
235
236         if (ret == 0) {
237                 ltdb_modified(ldb, msg->dn);
238         }
239
240         ltdb_unlock(ldb);
241         return ret;
242 }
243
244
245 /*
246   delete a record from the database, not updating indexes (used for deleting
247   index records)
248 */
249 int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn)
250 {
251         struct ltdb_private *ltdb = ldb->private_data;
252         TDB_DATA tdb_key;
253         int ret;
254
255         tdb_key = ltdb_key(ldb, dn);
256         if (!tdb_key.dptr) {
257                 return -1;
258         }
259
260         ret = tdb_delete(ltdb->tdb, tdb_key);
261         ldb_free(ldb, tdb_key.dptr);
262
263         return ret;
264 }
265
266 /*
267   delete a record from the database
268 */
269 static int ltdb_delete(struct ldb_context *ldb, const char *dn)
270 {
271         struct ltdb_private *ltdb = ldb->private_data;
272         int ret;
273         struct ldb_message msg;
274
275         ltdb->last_err_string = NULL;
276
277         if (ltdb_lock(ldb) != 0) {
278                 return -1;
279         }
280
281         if (ltdb_cache_load(ldb) != 0) {
282                 ltdb_unlock(ldb);
283                 return -1;
284         }
285
286         /* in case any attribute of the message was indexed, we need
287            to fetch the old record */
288         ret = ltdb_search_dn1(ldb, dn, &msg);
289         if (ret != 1) {
290                 /* not finding the old record is an error */
291                 goto failed;
292         }
293
294         ret = ltdb_delete_noindex(ldb, dn);
295         if (ret == -1) {
296                 ltdb_search_dn1_free(ldb, &msg);
297                 goto failed;
298         }
299
300         /* remove any indexed attributes */
301         ret = ltdb_index_del(ldb, &msg);
302
303         ltdb_search_dn1_free(ldb, &msg);
304
305         if (ret == 0) {
306                 ltdb_modified(ldb, dn);
307         }
308
309         ltdb_unlock(ldb);
310         return ret;
311
312 failed:
313         ltdb_unlock(ldb);
314         return -1;
315 }
316
317
318 /*
319   find an element by attribute name. At the moment this does a linear search, it should
320   be re-coded to use a binary search once all places that modify records guarantee
321   sorted order
322
323   return the index of the first matching element if found, otherwise -1
324 */
325 static int find_element(const struct ldb_message *msg, const char *name)
326 {
327         int i;
328         for (i=0;i<msg->num_elements;i++) {
329                 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
330                         return i;
331                 }
332         }
333         return -1;
334 }
335
336
337 /*
338   add an element to an existing record. Assumes a elements array that we
339   can call re-alloc on, and assumed that we can re-use the data pointers from the 
340   passed in additional values. Use with care!
341
342   returns 0 on success, -1 on failure (and sets errno)
343 */
344 static int msg_add_element(struct ldb_context *ldb,
345                            struct ldb_message *msg, struct ldb_message_element *el)
346 {
347         struct ldb_message_element *e2;
348         int i;
349
350         e2 = ldb_realloc_p(ldb, msg->elements, struct ldb_message_element, 
351                        msg->num_elements+1);
352         if (!e2) {
353                 errno = ENOMEM;
354                 return -1;
355         }
356
357         msg->elements = e2;
358
359         e2 = &msg->elements[msg->num_elements];
360
361         e2->name = el->name;
362         e2->flags = el->flags;
363         e2->values = NULL;
364         if (el->num_values != 0) {
365                 e2->values = ldb_malloc_array_p(ldb, struct ldb_val, el->num_values);
366                 if (!e2->values) {
367                         free(e2->name);
368                         errno = ENOMEM;
369                         return -1;
370                 }
371         }
372         for (i=0;i<el->num_values;i++) {
373                 e2->values[i] = el->values[i];
374         }
375         e2->num_values = el->num_values;
376
377         msg->num_elements++;
378
379         return 0;
380 }
381
382 /*
383   delete all elements having a specified attribute name
384 */
385 static int msg_delete_attribute(struct ldb_context *ldb,
386                                 struct ldb_message *msg, const char *name)
387 {
388         int i, count=0;
389         struct ldb_message_element *el2;
390
391         el2 = ldb_malloc_array_p(ldb, struct ldb_message_element, msg->num_elements);
392         if (!el2) {
393                 errno = ENOMEM;
394                 return -1;
395         }
396
397         for (i=0;i<msg->num_elements;i++) {
398                 if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
399                         el2[count++] = msg->elements[i];
400                 } else {
401                         ldb_free(ldb, msg->elements[i].values);
402                 }
403         }
404
405         msg->num_elements = count;
406         ldb_free(ldb, msg->elements);
407         msg->elements = el2;
408
409         return 0;
410 }
411
412 /*
413   delete all elements matching an attribute name/value 
414
415   return 0 on success, -1 on failure
416 */
417 static int msg_delete_element(struct ldb_context *ldb,
418                               struct ldb_message *msg, 
419                               const char *name,
420                               const struct ldb_val *val)
421 {
422         int i;
423         struct ldb_message_element *el;
424
425         i = find_element(msg, name);
426         if (i == -1) {
427                 return -1;
428         }
429
430         el = &msg->elements[i];
431
432         for (i=0;i<el->num_values;i++) {
433                 if (ldb_val_equal(ldb, msg->elements[i].name, &el->values[i], val)) {
434                         if (i<el->num_values-1) {
435                                 memmove(&el->values[i], &el->values[i+1],
436                                         sizeof(el->values[i])*(el->num_values-(i+1)));
437                         }
438                         el->num_values--;
439                         return 0;
440                 }
441         }
442         
443         return -1;
444 }
445
446
447 /*
448   modify a record - internal interface
449
450   yuck - this is O(n^2). Luckily n is usually small so we probably
451   get away with it, but if we ever have really large attribute lists 
452   then we'll need to look at this again
453 */
454 int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg)
455 {
456         struct ltdb_private *ltdb = ldb->private_data;
457         TDB_DATA tdb_key, tdb_data;
458         struct ldb_message msg2;
459         int ret, i, j;
460
461         tdb_key = ltdb_key(ldb, msg->dn);
462         if (!tdb_key.dptr) {
463                 return -1;
464         }
465
466         tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
467         if (!tdb_data.dptr) {
468                 free(tdb_key.dptr);
469                 return -1;
470         }
471
472         ret = ltdb_unpack_data(ldb, &tdb_data, &msg2);
473         if (ret == -1) {
474                 ldb_free(ldb, tdb_key.dptr);
475                 free(tdb_data.dptr);
476                 return -1;
477         }
478
479         if (!msg2.dn) {
480                 msg2.dn = msg->dn;
481         }
482
483         for (i=0;i<msg->num_elements;i++) {
484                 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
485
486                 case LDB_FLAG_MOD_ADD:
487                         /* add this element to the message. fail if it
488                            already exists */
489                         ret = find_element(&msg2, msg->elements[i].name);
490                         if (ret != -1) {
491                                 errno = EEXIST;
492                                 goto failed;
493                         }
494                         if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) {
495                                 goto failed;
496                         }
497                         break;
498
499                 case LDB_FLAG_MOD_REPLACE:
500                         /* replace all elements of this attribute name with the elements
501                            listed */
502                         if (msg_delete_attribute(ldb, &msg2, msg->elements[i].name) != 0) {
503                                 goto failed;
504                         }
505                         /* add the replacement element */
506                         if (msg_add_element(ldb, &msg2, &msg->elements[i]) != 0) {
507                                 goto failed;
508                         }
509                         break;
510
511                 case LDB_FLAG_MOD_DELETE:
512                         /* we could be being asked to delete all
513                            values or just some values */
514                         if (msg->elements[i].num_values == 0) {
515                                 if (msg_delete_attribute(ldb, &msg2, 
516                                                          msg->elements[i].name) != 0) {
517                                         goto failed;
518                                 }
519                                 break;
520                         }
521                         for (j=0;j<msg->elements[i].num_values;j++) {
522                                 if (msg_delete_element(ldb,
523                                                        &msg2, 
524                                                        msg->elements[i].name,
525                                                        &msg->elements[i].values[j]) != 0) {
526                                         goto failed;
527                                 }
528                         }
529                         break;
530                 }
531         }
532
533         /* we've made all the mods - save the modified record back into the database */
534         ret = ltdb_store(ldb, &msg2, TDB_MODIFY);
535
536         ldb_free(ldb, tdb_key.dptr);
537         free(tdb_data.dptr);
538         ltdb_unpack_data_free(ldb, &msg2);
539         return ret;
540
541 failed:
542         ldb_free(ldb, tdb_key.dptr);
543         free(tdb_data.dptr);
544         ltdb_unpack_data_free(ldb, &msg2);
545         return -1;
546 }
547
548 /*
549   modify a record
550 */
551 static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
552 {
553         struct ltdb_private *ltdb = ldb->private_data;
554         int ret;
555
556         ltdb->last_err_string = NULL;
557
558         if (ltdb_lock(ldb) != 0) {
559                 return -1;
560         }
561
562         if (ltdb_cache_load(ldb) != 0) {
563                 ltdb_unlock(ldb);
564                 return -1;
565         }
566
567         ret = ltdb_modify_internal(ldb, msg);
568
569         if (ret == 0) {
570                 ltdb_modified(ldb, msg->dn);
571         }
572
573         ltdb_unlock(ldb);
574
575         return ret;
576 }
577
578 /*
579   close database
580 */
581 static int ltdb_close(struct ldb_context *ldb)
582 {
583         struct ltdb_private *ltdb = ldb->private_data;
584         int ret;
585
586         ltdb->last_err_string = NULL;
587
588         ltdb_cache_free(ldb);
589         ldb_set_alloc(ldb, NULL, NULL);
590
591         ret = tdb_close(ltdb->tdb);
592         ldb_free(ldb, ltdb);
593         free(ldb);
594         return ret;
595 }
596                       
597
598 /*
599   return extended error information
600 */
601 static const char *ltdb_errstring(struct ldb_context *ldb)
602 {
603         struct ltdb_private *ltdb = ldb->private_data;
604         if (ltdb->last_err_string) {
605                 return ltdb->last_err_string;
606         }
607         return tdb_errorstr(ltdb->tdb);
608 }
609
610
611 static const struct ldb_backend_ops ltdb_ops = {
612         ltdb_close, 
613         ltdb_search,
614         ltdb_search_free,
615         ltdb_add,
616         ltdb_modify,
617         ltdb_delete,
618         ltdb_errstring,
619         ltdb_cache_free
620 };
621
622
623 /*
624   connect to the database
625 */
626 struct ldb_context *ltdb_connect(const char *url, 
627                                  unsigned int flags, 
628                                  const char *options[])
629 {
630         const char *path;
631         int tdb_flags, open_flags;
632         struct ltdb_private *ltdb;
633         TDB_CONTEXT *tdb;
634         struct ldb_context *ldb;
635
636         ldb = calloc(1, sizeof(struct ldb_context));
637         if (!ldb) {
638                 errno = ENOMEM;
639                 return NULL;
640         }
641
642         /* parse the url */
643         if (strchr(url, ':')) {
644                 if (strncmp(url, "tdb://", 6) != 0) {
645                         errno = EINVAL;
646                         return NULL;
647                 }
648                 path = url+6;
649         } else {
650                 path = url;
651         }
652
653         tdb_flags = TDB_DEFAULT;
654
655         if (flags & LDB_FLG_RDONLY) {
656                 open_flags = O_RDONLY;
657         } else {
658                 open_flags = O_CREAT | O_RDWR;
659         }
660
661         /* note that we use quite a large default hash size */
662         tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666);
663         if (!tdb) {
664                 free(ldb);
665                 return NULL;
666         }
667
668         ltdb = ldb_malloc_p(ldb, struct ltdb_private);
669         if (!ltdb) {
670                 tdb_close(tdb);
671                 free(ldb);
672                 errno = ENOMEM;
673                 return NULL;
674         }
675
676         ltdb->tdb = tdb;
677         ltdb->sequence_number = 0;
678
679         memset(&ltdb->cache, 0, sizeof(ltdb->cache));
680
681         ldb->private_data = ltdb;
682         ldb->ops = &ltdb_ops;
683
684         return ldb;
685 }