summaryrefslogtreecommitdiff
path: root/source4/lib/ldb/ldb_tdb/ldb_cache.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-05-01 09:45:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:51:38 -0500
commit0dad5a34273bf5cadcfd4a36d69bdffbf69eb073 (patch)
tree78ddbe4e053287a0e7a0300e945627ce4b24bc29 /source4/lib/ldb/ldb_tdb/ldb_cache.c
parenta2b6d47390a07f0d2a737d17144f825a9733d5bf (diff)
downloadsamba-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.c229
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 = &el;
+ 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, &ltdb->cache.baseinfo);
+ ltdb_search_dn1_free(ldb, &ltdb->cache.indexlist);
+ ltdb_search_dn1_free(ldb, &ltdb->cache.subclasses);
+ ltdb_search_dn1_free(ldb, &ltdb->cache.attributes);
+
+ if (ltdb->cache.last_attribute.name) free(ltdb->cache.last_attribute.name);
+ memset(&ltdb->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, &ltdb->cache.baseinfo);
+
+ if (ltdb_search_dn1(ldb, LTDB_BASEINFO, &ltdb->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, &ltdb->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(&ltdb->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(&ltdb->cache.last_attribute, 0, sizeof(ltdb->cache.last_attribute));
+
+ ltdb_search_dn1_free(ldb, &ltdb->cache.indexlist);
+ ltdb_search_dn1_free(ldb, &ltdb->cache.subclasses);
+ ltdb_search_dn1_free(ldb, &ltdb->cache.attributes);
+
+ if (ltdb_search_dn1(ldb, LTDB_INDEXLIST, &ltdb->cache.indexlist) == -1) {
+ return -1;
+ }
+ if (ltdb_search_dn1(ldb, LTDB_SUBCLASSES, &ltdb->cache.subclasses) == -1) {
+ return -1;
+ }
+ if (ltdb_search_dn1(ldb, LTDB_ATTRIBUTES, &ltdb->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 = &el;
+ 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(&ltdb->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;
+}