4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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
28 * Component: ldb tdb backend
30 * Description: core functions for tdb backend
32 * Author: Andrew Tridgell
36 #include "ldb/ldb_tdb/ldb_tdb.h"
39 form a TDB_DATA for a record key
42 note that the key for a record can depend on whether the
43 dn refers to a case sensitive index record or not
45 struct TDB_DATA ltdb_key(struct ldb_context *ldb, const char *dn)
49 char *dn_folded = NULL;
50 const char *prefix = LTDB_INDEX ":";
55 most DNs are case insensitive. The exception is index DNs for
56 case sensitive attributes
58 if (strncmp(dn, prefix, strlen(prefix)) == 0 &&
59 (s = strchr(dn+strlen(prefix), ':'))) {
60 char *attr_name, *attr_name_folded;
61 attr_name = strndup(dn+strlen(prefix), (s-(dn+strlen(prefix))));
65 flags = ltdb_attribute_flags(ldb, attr_name);
67 if (flags & LTDB_FLAG_CASE_INSENSITIVE) {
68 dn_folded = ldb_casefold(dn);
70 attr_name_folded = ldb_casefold(attr_name);
71 if (!attr_name_folded) {
74 asprintf(&dn_folded, "%s:%s:%s",
75 prefix, attr_name_folded,
77 free(attr_name_folded);
81 dn_folded = ldb_casefold(dn);
88 asprintf(&key_str, "DN=%s", dn_folded);
96 key.dsize = strlen(key_str)+1;
108 lock the database for write - currently a single lock is used
110 static int ltdb_lock(struct ldb_context *ldb)
112 struct ltdb_private *ltdb = ldb->private_data;
116 key = ltdb_key(ldb, "LDBLOCK");
121 ret = tdb_chainlock(ltdb->tdb, key);
129 unlock the database after a ltdb_lock()
131 static void ltdb_unlock(struct ldb_context *ldb)
133 struct ltdb_private *ltdb = ldb->private_data;
136 key = ltdb_key(ldb, "LDBLOCK");
141 tdb_chainunlock(ltdb->tdb, key);
148 we've made a modification to a dn - possibly reindex and
149 update sequence number
151 static int ltdb_modified(struct ldb_context *ldb, const char *dn)
155 if (strcmp(dn, LTDB_INDEXLIST) == 0 ||
156 strcmp(dn, LTDB_ATTRIBUTES) == 0) {
157 ret = ltdb_reindex(ldb);
161 strcmp(dn, LTDB_BASEINFO) != 0) {
162 ret = ltdb_increase_sequence_number(ldb);
169 store a record into the db
171 int ltdb_store(struct ldb_context *ldb, const struct ldb_message *msg, int flgs)
173 struct ltdb_private *ltdb = ldb->private_data;
174 TDB_DATA tdb_key, tdb_data;
177 tdb_key = ltdb_key(ldb, msg->dn);
182 ret = ltdb_pack_data(ldb, msg, &tdb_data);
188 ret = tdb_store(ltdb->tdb, tdb_key, tdb_data, flgs);
193 ret = ltdb_index_add(ldb, msg);
195 tdb_delete(ltdb->tdb, tdb_key);
207 add a record to the database
209 static int ltdb_add(struct ldb_context *ldb, const struct ldb_message *msg)
213 if (ltdb_lock(ldb) != 0) {
217 if (ltdb_cache_load(ldb) != 0) {
222 ret = ltdb_store(ldb, msg, TDB_INSERT);
225 ltdb_modified(ldb, msg->dn);
234 delete a record from the database, not updating indexes (used for deleting
237 int ltdb_delete_noindex(struct ldb_context *ldb, const char *dn)
239 struct ltdb_private *ltdb = ldb->private_data;
243 tdb_key = ltdb_key(ldb, dn);
248 ret = tdb_delete(ltdb->tdb, tdb_key);
255 delete a record from the database
257 static int ltdb_delete(struct ldb_context *ldb, const char *dn)
260 struct ldb_message msg;
262 if (ltdb_lock(ldb) != 0) {
266 if (ltdb_cache_load(ldb) != 0) {
271 /* in case any attribute of the message was indexed, we need
272 to fetch the old record */
273 ret = ltdb_search_dn1(ldb, dn, &msg);
275 /* not finding the old record is an error */
279 ret = ltdb_delete_noindex(ldb, dn);
281 ltdb_search_dn1_free(ldb, &msg);
285 /* remove any indexed attributes */
286 ret = ltdb_index_del(ldb, &msg);
288 ltdb_search_dn1_free(ldb, &msg);
291 ltdb_modified(ldb, dn);
304 find an element by attribute name. At the moment this does a linear search, it should
305 be re-coded to use a binary search once all places that modify records guarantee
308 return the index of the first matching element if found, otherwise -1
310 static int find_element(const struct ldb_message *msg, const char *name)
313 for (i=0;i<msg->num_elements;i++) {
314 if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
323 add an element to an existing record. Assumes a elements array that we
324 can call re-alloc on, and assumed that we can re-use the data pointers from the
325 passed in additional values. Use with care!
327 returns 0 on success, -1 on failure (and sets errno)
329 static int msg_add_element(struct ldb_message *msg, struct ldb_message_element *el)
331 struct ldb_message_element *e2;
334 e2 = realloc_p(msg->elements, struct ldb_message_element,
335 msg->num_elements+1);
343 e2 = &msg->elements[msg->num_elements];
346 e2->flags = el->flags;
348 if (el->num_values != 0) {
349 e2->values = malloc_array_p(struct ldb_val, el->num_values);
356 for (i=0;i<el->num_values;i++) {
357 e2->values[i] = el->values[i];
359 e2->num_values = el->num_values;
367 delete all elements having a specified attribute name
369 static int msg_delete_attribute(struct ldb_message *msg, const char *name)
372 struct ldb_message_element *el2;
374 el2 = malloc_array_p(struct ldb_message_element, msg->num_elements);
380 for (i=0;i<msg->num_elements;i++) {
381 if (ldb_attr_cmp(msg->elements[i].name, name) != 0) {
382 el2[count++] = msg->elements[i];
384 if (msg->elements[i].values) free(msg->elements[i].values);
388 msg->num_elements = count;
389 if (msg->elements) free(msg->elements);
396 delete all elements matching an attribute name/value
398 return 0 on success, -1 on failure
400 static int msg_delete_element(struct ldb_context *ldb,
401 struct ldb_message *msg,
403 const struct ldb_val *val)
406 struct ldb_message_element *el;
408 i = find_element(msg, name);
413 el = &msg->elements[i];
415 for (i=0;i<el->num_values;i++) {
416 if (ldb_val_equal(ldb, msg->elements[i].name, &el->values[i], val)) {
417 if (i<el->num_values-1) {
418 memmove(&el->values[i], &el->values[i+1],
419 sizeof(el->values[i])*el->num_values-(i+1));
431 modify a record - internal interface
433 yuck - this is O(n^2). Luckily n is usually small so we probably
434 get away with it, but if we ever have really large attribute lists
435 then we'll need to look at this again
437 int ltdb_modify_internal(struct ldb_context *ldb, const struct ldb_message *msg)
439 struct ltdb_private *ltdb = ldb->private_data;
440 TDB_DATA tdb_key, tdb_data;
441 struct ldb_message msg2;
444 tdb_key = ltdb_key(ldb, msg->dn);
449 tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
450 if (!tdb_data.dptr) {
455 ret = ltdb_unpack_data(ldb, &tdb_data, &msg2);
466 for (i=0;i<msg->num_elements;i++) {
467 switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
469 case LDB_FLAG_MOD_ADD:
470 /* add this element to the message. fail if it
472 ret = find_element(&msg2, msg->elements[i].name);
477 if (msg_add_element(&msg2, &msg->elements[i]) != 0) {
482 case LDB_FLAG_MOD_REPLACE:
483 /* replace all elements of this attribute name with the elements
485 if (msg_delete_attribute(&msg2, msg->elements[i].name) != 0) {
488 /* add the replacement element */
489 if (msg_add_element(&msg2, &msg->elements[i]) != 0) {
494 case LDB_FLAG_MOD_DELETE:
495 /* we could be being asked to delete all
496 values or just some values */
497 if (msg->elements[i].num_values == 0) {
498 if (msg_delete_attribute(&msg2,
499 msg->elements[i].name) != 0) {
504 for (j=0;j<msg->elements[i].num_values;j++) {
505 if (msg_delete_element(ldb,
507 msg->elements[i].name,
508 &msg->elements[i].values[j]) != 0) {
516 /* we've made all the mods - save the modified record back into the database */
517 ret = ltdb_store(ldb, &msg2, TDB_MODIFY);
521 ltdb_unpack_data_free(&msg2);
527 ltdb_unpack_data_free(&msg2);
534 static int ltdb_modify(struct ldb_context *ldb, const struct ldb_message *msg)
538 if (ltdb_lock(ldb) != 0) {
542 if (ltdb_cache_load(ldb) != 0) {
547 ret = ltdb_modify_internal(ldb, msg);
550 ltdb_modified(ldb, msg->dn);
561 static int ltdb_close(struct ldb_context *ldb)
563 struct ltdb_private *ltdb = ldb->private_data;
566 ltdb_cache_free(ldb);
568 ret = tdb_close(ltdb->tdb);
576 return extended error information
578 static const char *ltdb_errstring(struct ldb_context *ldb)
580 struct ltdb_private *ltdb = ldb->private_data;
581 return tdb_errorstr(ltdb->tdb);
585 static const struct ldb_backend_ops ltdb_ops = {
597 connect to the database
599 struct ldb_context *ltdb_connect(const char *url,
601 const char *options[])
604 int tdb_flags, open_flags;
605 struct ltdb_private *ltdb;
607 struct ldb_context *ldb;
610 if (strncmp(url, "tdb://", 6) != 0) {
617 tdb_flags = TDB_DEFAULT;
619 if (flags & LDB_FLG_RDONLY) {
620 open_flags = O_RDONLY;
622 open_flags = O_CREAT | O_RDWR;
625 /* note that we use quite a large default hash size */
626 tdb = tdb_open(path, 10000, tdb_flags, open_flags, 0666);
631 ltdb = malloc_p(struct ltdb_private);
639 ltdb->sequence_number = 0;
641 memset(<db->cache, 0, sizeof(ltdb->cache));
643 ldb = malloc_p(struct ldb_context);
651 ldb->private_data = ltdb;
652 ldb->ops = <db_ops;