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 cache functions
30 * Description: cache special records in a ldb/tdb
32 * Author: Andrew Tridgell
36 #include "ldb/include/ldb.h"
37 #include "ldb/include/ldb_private.h"
38 #include "ldb/ldb_tdb/ldb_tdb.h"
41 initialise the baseinfo record
43 static int ltdb_baseinfo_init(struct ldb_module *module)
45 struct ldb_context *ldb = module->ldb;
46 struct ltdb_private *ltdb = module->private_data;
47 struct ldb_message msg;
48 struct ldb_message_element el;
51 /* the initial sequence number must be different from the one
52 set in ltdb_cache_free(). Thanks to Jon for pointing this
54 const char *initial_sequence_number = "1";
56 ltdb->sequence_number = atof(initial_sequence_number);
60 msg.dn = ldb_strdup(ldb, LTDB_BASEINFO);
65 el.name = ldb_strdup(ldb, LTDB_SEQUENCE_NUMBER);
67 ldb_free(ldb, msg.dn);
74 val.data = ldb_strdup(ldb, initial_sequence_number);
76 ldb_free(ldb, el.name);
77 ldb_free(ldb, msg.dn);
83 ret = ltdb_store(module, &msg, TDB_INSERT);
85 ldb_free(ldb, msg.dn);
86 ldb_free(ldb, el.name);
87 ldb_free(ldb, val.data);
93 free any cache records
95 void ltdb_cache_free(struct ldb_module *module)
97 struct ldb_context *ldb = module->ldb;
98 struct ltdb_private *ltdb = module->private_data;
99 struct ldb_alloc_ops alloc = ldb->alloc_ops;
100 ldb->alloc_ops.alloc = NULL;
102 ltdb->sequence_number = 0;
103 ltdb_search_dn1_free(module, <db->cache.baseinfo);
104 ltdb_search_dn1_free(module, <db->cache.indexlist);
105 ltdb_search_dn1_free(module, <db->cache.subclasses);
106 ltdb_search_dn1_free(module, <db->cache.attributes);
108 ldb_free(ldb, ltdb->cache.last_attribute.name);
109 memset(<db->cache, 0, sizeof(ltdb->cache));
111 ldb->alloc_ops = alloc;
115 load the cache records
117 int ltdb_cache_load(struct ldb_module *module)
119 struct ldb_context *ldb = module->ldb;
120 struct ltdb_private *ltdb = module->private_data;
122 struct ldb_alloc_ops alloc = ldb->alloc_ops;
124 ldb->alloc_ops.alloc = NULL;
126 ltdb_search_dn1_free(module, <db->cache.baseinfo);
128 if (ltdb_search_dn1(module, LTDB_BASEINFO, <db->cache.baseinfo) == -1) {
132 /* possibly initialise the baseinfo */
133 if (!ltdb->cache.baseinfo.dn) {
134 if (ltdb_baseinfo_init(module) != 0) {
137 if (ltdb_search_dn1(module, LTDB_BASEINFO, <db->cache.baseinfo) != 1) {
142 /* if the current internal sequence number is the same as the one
143 in the database then assume the rest of the cache is OK */
144 seq = ldb_msg_find_double(<db->cache.baseinfo, LTDB_SEQUENCE_NUMBER, 0);
145 if (seq == ltdb->sequence_number) {
148 ltdb->sequence_number = seq;
150 ldb_free(ldb, ltdb->cache.last_attribute.name);
151 memset(<db->cache.last_attribute, 0, sizeof(ltdb->cache.last_attribute));
153 ltdb_search_dn1_free(module, <db->cache.indexlist);
154 ltdb_search_dn1_free(module, <db->cache.subclasses);
155 ltdb_search_dn1_free(module, <db->cache.attributes);
157 if (ltdb_search_dn1(module, LTDB_INDEXLIST, <db->cache.indexlist) == -1) {
160 if (ltdb_search_dn1(module, LTDB_SUBCLASSES, <db->cache.subclasses) == -1) {
163 if (ltdb_search_dn1(module, LTDB_ATTRIBUTES, <db->cache.attributes) == -1) {
168 ldb->alloc_ops = alloc;
172 ldb->alloc_ops = alloc;
178 increase the sequence number to indicate a database change
180 int ltdb_increase_sequence_number(struct ldb_module *module)
182 struct ldb_context *ldb = module->ldb;
183 struct ltdb_private *ltdb = module->private_data;
184 struct ldb_message msg;
185 struct ldb_message_element el;
190 ldb_asprintf(ldb, &s, "%.0f", ltdb->sequence_number+1);
196 msg.num_elements = 1;
198 msg.dn = ldb_strdup(ldb, LTDB_BASEINFO);
199 el.name = ldb_strdup(ldb, LTDB_SEQUENCE_NUMBER);
202 el.flags = LDB_FLAG_MOD_REPLACE;
204 val.length = strlen(s);
206 ret = ltdb_modify_internal(module, &msg);
209 ldb_free(ldb, msg.dn);
210 ldb_free(ldb, el.name);
213 ltdb->sequence_number += 1;
221 return the attribute flags from the @ATTRIBUTES record
222 for the given attribute
224 int ltdb_attribute_flags(struct ldb_module *module, const char *attr_name)
226 struct ldb_context *ldb = module->ldb;
227 struct ltdb_private *ltdb = module->private_data;
233 { "CASE_INSENSITIVE", LTDB_FLAG_CASE_INSENSITIVE },
234 { "INTEGER", LTDB_FLAG_INTEGER },
235 { "WILDCARD", LTDB_FLAG_WILDCARD },
236 { "HIDDEN", LTDB_FLAG_HIDDEN },
241 struct ldb_alloc_ops alloc = ldb->alloc_ops;
243 if (ltdb->cache.last_attribute.name &&
244 ldb_attr_cmp(ltdb->cache.last_attribute.name, attr_name) == 0) {
245 return ltdb->cache.last_attribute.flags;
248 /* objectclass is a special default case */
249 if (ldb_attr_cmp(attr_name, LTDB_OBJECTCLASS) == 0) {
250 ret = LTDB_FLAG_OBJECTCLASS | LTDB_FLAG_CASE_INSENSITIVE;
253 attrs = ldb_msg_find_string(<db->cache.attributes, attr_name, NULL);
259 /* we avoid using strtok and friends due to their nasty
260 interface. This is a little trickier, but much nicer
261 from a C interface point of view */
262 while ((len = strcspn(attrs, " ,")) > 0) {
263 for (i=0;names[i].name;i++) {
264 if (strncmp(names[i].name, attrs, len) == 0 &&
265 names[i].name[len] == 0) {
266 ret |= names[i].value;
270 attrs += strspn(attrs, " ,");
273 ldb->alloc_ops.alloc = NULL;
275 ldb_free(ldb, ltdb->cache.last_attribute.name);
277 ltdb->cache.last_attribute.name = ldb_strdup(ldb, attr_name);
278 ltdb->cache.last_attribute.flags = ret;
280 ldb->alloc_ops = alloc;