diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-05-01 09:45:56 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:51:38 -0500 |
commit | 0dad5a34273bf5cadcfd4a36d69bdffbf69eb073 (patch) | |
tree | 78ddbe4e053287a0e7a0300e945627ce4b24bc29 /source4/lib/ldb/ldb_tdb/ldb_cache.c | |
parent | a2b6d47390a07f0d2a737d17144f825a9733d5bf (diff) | |
download | samba-0dad5a34273bf5cadcfd4a36d69bdffbf69eb073.tar.gz samba-0dad5a34273bf5cadcfd4a36d69bdffbf69eb073.tar.bz2 samba-0dad5a34273bf5cadcfd4a36d69bdffbf69eb073.zip |
r435: a major upgrade for ldb
- added the ability to mark record attributes as being CASE_INSENSITIVE, WILDCARD or INTEGER.
- added the ability to support objectclass subclasses, and to search by a parent class
- added internal support for case insensitive versus case sensitive
indexing (not UTF8 compliant yet)
- cleaned up a number of const warnings
- added a number of helper functions for fetching integers, strings and doubles
- added a in-memory cache for important database properties, supported by a
database sequence number
- changed some variable names to avoid conflicts with C++
(This used to be commit f2bf06f25c2e6c744817711c7bedbd1d3b52f994)
Diffstat (limited to 'source4/lib/ldb/ldb_tdb/ldb_cache.c')
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_cache.c | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c new file mode 100644 index 0000000000..5d61fd35b3 --- /dev/null +++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c @@ -0,0 +1,229 @@ +/* + ldb database library + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the ldb + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + * Name: ldb + * + * Component: ldb tdb cache functions + * + * Description: cache special records in a ldb/tdb + * + * Author: Andrew Tridgell + */ + +#include "includes.h" +#include "ldb/ldb_tdb/ldb_tdb.h" + +/* + initialise the baseinfo record +*/ +static int ltdb_baseinfo_init(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + struct ldb_message msg; + struct ldb_message_element el; + struct ldb_val val; + + ltdb->sequence_number = 0; + + msg.num_elements = 1; + msg.elements = ⪙ + msg.dn = LTDB_BASEINFO; + el.name = LTDB_SEQUENCE_NUMBER; + el.values = &val; + el.num_values = 1; + el.flags = 0; + val.data = "0"; + val.length = 1; + + return ltdb_store(ldb, &msg, TDB_INSERT); +} + +/* + free any cache records + */ +void ltdb_cache_free(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + + ltdb->sequence_number = 0; + ltdb_search_dn1_free(ldb, <db->cache.baseinfo); + ltdb_search_dn1_free(ldb, <db->cache.indexlist); + ltdb_search_dn1_free(ldb, <db->cache.subclasses); + ltdb_search_dn1_free(ldb, <db->cache.attributes); + + if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + memset(<db->cache, 0, sizeof(ltdb->cache)); +} + +/* + load the cache records +*/ +int ltdb_cache_load(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + double seq; + + ltdb_search_dn1_free(ldb, <db->cache.baseinfo); + + if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) == -1) { + return -1; + } + + /* possibly initialise the baseinfo */ + if (!ltdb->cache.baseinfo.dn) { + if (ltdb_baseinfo_init(ldb) != 0) { + return -1; + } + if (ltdb_search_dn1(ldb, LTDB_BASEINFO, <db->cache.baseinfo) != 1) { + return -1; + } + } + + /* if the current internal sequence number is the same as the one + in the database then assume the rest of the cache is OK */ + seq = ldb_msg_find_double(<db->cache.baseinfo, LTDB_SEQUENCE_NUMBER, 0); + if (seq == ltdb->sequence_number) { + return 0; + } + ltdb->sequence_number = seq; + + if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + memset(<db->cache.last_attribute, 0, sizeof(ltdb->cache.last_attribute)); + + ltdb_search_dn1_free(ldb, <db->cache.indexlist); + ltdb_search_dn1_free(ldb, <db->cache.subclasses); + ltdb_search_dn1_free(ldb, <db->cache.attributes); + + if (ltdb_search_dn1(ldb, LTDB_INDEXLIST, <db->cache.indexlist) == -1) { + return -1; + } + if (ltdb_search_dn1(ldb, LTDB_SUBCLASSES, <db->cache.subclasses) == -1) { + return -1; + } + if (ltdb_search_dn1(ldb, LTDB_ATTRIBUTES, <db->cache.attributes) == -1) { + return -1; + } + + return 0; +} + + +/* + increase the sequence number to indicate a database change +*/ +int ltdb_increase_sequence_number(struct ldb_context *ldb) +{ + struct ltdb_private *ltdb = ldb->private_data; + struct ldb_message msg; + struct ldb_message_element el; + struct ldb_val val; + char *s = NULL; + int ret; + + asprintf(&s, "%.0f", ltdb->sequence_number+1); + if (!s) { + errno = ENOMEM; + return -1; + } + + msg.num_elements = 1; + msg.elements = ⪙ + msg.dn = LTDB_BASEINFO; + el.name = LTDB_SEQUENCE_NUMBER; + el.values = &val; + el.num_values = 1; + el.flags = LDB_FLAG_MOD_REPLACE; + val.data = s; + val.length = strlen(s); + + ret = ltdb_modify_internal(ldb, &msg); + + free(s); + + if (ret == 0) { + ltdb->sequence_number += 1; + } + + return ret; +} + + +/* + return the attribute flags from the @ATTRIBUTES record + for the given attribute +*/ +int ltdb_attribute_flags(struct ldb_context *ldb, const char *attr_name) +{ + struct ltdb_private *ltdb = ldb->private_data; + const char *attrs; + const struct { + const char *name; + int value; + } names[] = { + { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE }, + { "INTEGER", LTDB_FLAG_INTEGER }, + { "WILDCARD", LTDB_FLAG_WILDCARD }, + { NULL, 0} + }; + size_t len; + int i, ret=0; + + if (ltdb->cache.last_attribute.name && + ldb_attr_cmp(ltdb->cache.last_attribute.name, attr_name) == 0) { + return ltdb->cache.last_attribute.flags; + } + + /* objectclass is a special default case */ + if (ldb_attr_cmp(attr_name, LTDB_OBJECTCLASS) == 0) { + ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE; + } + + attrs = ldb_msg_find_string(<db->cache.attributes, attr_name, NULL); + + if (!attrs) { + return ret; + } + + /* we avoid using strtok and friends due to their nasty + interface. This is a little trickier, but much nicer + from a C interface point of view */ + while ((len = strcspn(attrs, " ,")) > 0) { + for (i=0;names[i].name;i++) { + if (strncmp(names[i].name, attrs, len) == 0 && + names[i].name[len] == 0) { + ret |= names[i].value; + } + } + attrs += len; + attrs += strspn(attrs, " ,"); + } + + if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name); + + ltdb->cache.last_attribute.name = strdup(attr_name); + ltdb->cache.last_attribute.flags = ret; + + return ret; +} |