[dovecot-cvs] dovecot/src/plugins/acl acl-api-private.h, 1.1,
1.2 acl-api.c, 1.1, 1.2 acl-backend-vfile.c, 1.1,
1.2 acl-backend.c, 1.1, 1.2 acl-cache.c, 1.1, 1.2 acl-cache.h,
1.1, 1.2 acl-storage.c, 1.1, 1.2
tss-movial at dovecot.org
tss-movial at dovecot.org
Tue Feb 28 14:38:24 EET 2006
Update of /var/lib/cvs/dovecot/src/plugins/acl
In directory talvi:/tmp/cvs-serv32291/plugins/acl
Modified Files:
acl-api-private.h acl-api.c acl-backend-vfile.c acl-backend.c
acl-cache.c acl-cache.h acl-storage.c
Log Message:
Don't keep acl_objects permanently in memory. Moved cache validity information into cache records. Some other cleanups and fixes.
Index: acl-api-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-api-private.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- acl-api-private.h 27 Feb 2006 16:30:39 -0000 1.1
+++ acl-api-private.h 28 Feb 2006 12:38:20 -0000 1.2
@@ -33,13 +33,10 @@
struct acl_cache *cache;
struct acl_mask *default_rights;
- struct hash_table *aclobjs;
struct acl_backend_vfuncs v;
};
struct acl_object {
- int refcount;
-
struct acl_backend *backend;
char *name;
};
Index: acl-api.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-api.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- acl-api.c 27 Feb 2006 16:30:39 -0000 1.1
+++ acl-api.c 28 Feb 2006 12:38:20 -0000 1.2
@@ -9,23 +9,10 @@
struct acl_object *acl_object_init_from_name(struct acl_backend *backend,
const char *name)
{
- struct acl_object *aclobj;
- const char *control_dir;
-
- aclobj = hash_lookup(backend->aclobjs, name);
- if (aclobj != NULL) {
- i_assert(aclobj->refcount >= 0);
- aclobj->refcount++;
- return aclobj;
- }
-
- control_dir =
+ const char *control_dir =
mail_storage_get_mailbox_control_dir(backend->storage, name);
- aclobj = backend->v.object_init(backend, name, control_dir);
- aclobj->refcount++;
- hash_insert(backend->aclobjs, aclobj->name, aclobj);
- return aclobj;
+ return backend->v.object_init(backend, name, control_dir);
}
struct acl_object *acl_object_init_from_mailbox(struct acl_backend *backend,
@@ -40,14 +27,8 @@
{
struct acl_object *aclobj = *_aclobj;
- i_assert(aclobj->refcount > 0);
-
*_aclobj = NULL;
- if (--aclobj->refcount > 0)
- return;
-
- /* currently ACL objects are really freed only at backend
- deinitialization. */
+ aclobj->backend->v.object_deinit(aclobj);
}
int acl_object_have_right(struct acl_object *aclobj, unsigned int right_idx)
Index: acl-backend-vfile.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-backend-vfile.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- acl-backend-vfile.c 27 Feb 2006 16:30:39 -0000 1.1
+++ acl-backend-vfile.c 28 Feb 2006 12:38:20 -0000 1.2
@@ -18,14 +18,16 @@
#define ACL_SYNC_SECS 1
#define ACL_ESTALE_RETRY_COUNT NFS_ESTALE_RETRY_COUNT
-struct acl_vfile {
- char *path;
-
+struct acl_vfile_validity {
time_t last_read_time;
time_t last_mtime;
off_t last_size;
};
+struct acl_backend_vfile_validity {
+ struct acl_vfile_validity global_validity, local_validity;
+};
+
struct acl_backend_vfile {
struct acl_backend backend;
const char *global_dir;
@@ -34,7 +36,7 @@
struct acl_object_vfile {
struct acl_object aclobj;
- struct acl_vfile global_file, local_file;
+ char *global_path, *local_path;
};
struct acl_letter_map {
@@ -65,6 +67,9 @@
backend = p_new(pool, struct acl_backend_vfile, 1);
backend->global_dir = p_strdup(pool, data);
backend->backend.pool = pool;
+ backend->backend.cache =
+ acl_cache_init(&backend->backend,
+ sizeof(struct acl_backend_vfile_validity));
return &backend->backend;
}
@@ -84,9 +89,9 @@
aclobj = i_new(struct acl_object_vfile, 1);
aclobj->aclobj.backend = _backend;
aclobj->aclobj.name = i_strdup(name);
- aclobj->global_file.path =
+ aclobj->global_path =
i_strconcat(backend->global_dir, "/", name, NULL);
- aclobj->local_file.path =
+ aclobj->local_path =
i_strconcat(control_dir, "/"ACL_FILENAME, NULL);
return &aclobj->aclobj;
}
@@ -95,8 +100,8 @@
{
struct acl_object_vfile *aclobj = (struct acl_object_vfile *)_aclobj;
- i_free(aclobj->local_file.path);
- i_free(aclobj->global_file.path);
+ i_free(aclobj->local_path);
+ i_free(aclobj->global_path);
i_free(aclobj->aclobj.name);
i_free(aclobj);
}
@@ -143,7 +148,7 @@
}
static int
-acl_object_vfile_parse_line(struct acl_object *aclobj, struct acl_vfile *file,
+acl_object_vfile_parse_line(struct acl_object *aclobj, const char *path,
const char *line, unsigned int linenum)
{
struct acl_rights rights;
@@ -198,7 +203,7 @@
if (error != NULL) {
mail_storage_set_critical(aclobj->backend->storage,
"ACL file %s line %u: %s",
- file->path, linenum, error);
+ path, linenum, error);
t_pop();
return -1;
}
@@ -210,8 +215,8 @@
}
static int
-acl_backend_vfile_read(struct acl_object *aclobj, struct acl_vfile *file,
- bool try_retry)
+acl_backend_vfile_read(struct acl_object *aclobj, const char *path,
+ struct acl_vfile_validity *validity, bool try_retry)
{
struct mail_storage *storage = aclobj->backend->storage;
struct istream *input;
@@ -220,21 +225,22 @@
unsigned int linenum;
int fd, ret = 1;
- fd = nfs_safe_open(file->path, O_RDONLY);
+ fd = nfs_safe_open(path, O_RDONLY);
if (fd == -1) {
if (errno == ENOENT) {
- file->last_read_time = ioloop_time;
+ validity->last_size = 0;
+ validity->last_mtime = 0;
+ validity->last_read_time = ioloop_time;
return 1;
}
- mail_storage_set_critical(storage,
- "open(%s) failed: %m", file->path);
+ mail_storage_set_critical(storage, "open(%s) failed: %m", path);
return -1;
}
input = i_stream_create_file(fd, default_pool, 4096, FALSE);
linenum = 1;
while ((line = i_stream_read_next_line(input)) != NULL) {
- if (acl_object_vfile_parse_line(aclobj, file, line,
+ if (acl_object_vfile_parse_line(aclobj, path, line,
linenum++) < 0) {
ret = -1;
break;
@@ -247,7 +253,7 @@
else {
ret = -1;
mail_storage_set_critical(storage,
- "read(%s) failed: %m", file->path);
+ "read(%s) failed: %m", path);
}
}
@@ -258,12 +264,12 @@
else {
ret = -1;
mail_storage_set_critical(storage,
- "read(%s) failed: %m", file->path);
+ "read(%s) failed: %m", path);
}
} else {
- file->last_read_time = ioloop_time;
- file->last_mtime = st.st_mtime;
- file->last_size = st.st_size;
+ validity->last_read_time = ioloop_time;
+ validity->last_mtime = st.st_mtime;
+ validity->last_size = st.st_size;
}
}
@@ -273,21 +279,21 @@
return 0;
mail_storage_set_critical(storage, "close(%s) failed: %m",
- file->path);
+ path);
return -1;
}
return ret;
}
static int
-acl_backend_vfile_read_with_retry(struct acl_object *aclobj,
- struct acl_vfile *file)
+acl_backend_vfile_read_with_retry(struct acl_object *aclobj, const char *path,
+ struct acl_vfile_validity *validity)
{
unsigned int i;
int ret;
for (i = 0;; i++) {
- ret = acl_backend_vfile_read(aclobj, file,
+ ret = acl_backend_vfile_read(aclobj, path, validity,
i < ACL_ESTALE_RETRY_COUNT);
if (ret != 0)
break;
@@ -299,32 +305,33 @@
}
static int
-acl_backend_vfile_refresh(struct acl_object *aclobj, struct acl_vfile *file)
+acl_backend_vfile_refresh(struct acl_object *aclobj, const char *path,
+ const struct acl_vfile_validity *validity)
{
struct stat st;
- if (file->last_read_time == 0)
+ if (validity == NULL)
return 1;
- if (stat(file->path, &st) < 0) {
+ if (stat(path, &st) < 0) {
if (errno == ENOENT) {
- /* No global ACL directory */
- return 0;
- }
+ /* if the file used to exist, we have to re-read it */
+ return validity->last_mtime != 0;
+ }
mail_storage_set_critical(aclobj->backend->storage,
- "stat(%s) failed: %m", file->path);
+ "stat(%s) failed: %m", path);
return -1;
}
- if (st.st_mtime == file->last_mtime &&
- st.st_size == file->last_size) {
+ if (st.st_mtime == validity->last_mtime &&
+ st.st_size == validity->last_size) {
/* same timestamp, but if it was modified within the
same second we want to refresh it again later (but
do it only after a couple of seconds so we don't
keep re-reading it all the time within those
seconds) */
- if (st.st_mtime < file->last_read_time - ACL_SYNC_SECS ||
- ioloop_time - file->last_read_time <= ACL_SYNC_SECS)
+ if (st.st_mtime < validity->last_read_time - ACL_SYNC_SECS ||
+ ioloop_time - validity->last_read_time <= ACL_SYNC_SECS)
return 0;
}
@@ -334,21 +341,36 @@
static int acl_backend_vfile_object_refresh_cache(struct acl_object *_aclobj)
{
struct acl_object_vfile *aclobj = (struct acl_object_vfile *)_aclobj;
+ const struct acl_backend_vfile_validity *old_validity;
+ struct acl_backend_vfile_validity validity;
int ret;
- ret = acl_backend_vfile_refresh(_aclobj, &aclobj->global_file);
- if (ret == 0)
- ret = acl_backend_vfile_refresh(_aclobj, &aclobj->local_file);
+ old_validity = acl_cache_get_validity(_aclobj->backend->cache,
+ _aclobj->name);
+ ret = acl_backend_vfile_refresh(_aclobj, aclobj->global_path,
+ old_validity == NULL ? NULL :
+ &old_validity->global_validity);
+ if (ret == 0) {
+ ret = acl_backend_vfile_refresh(_aclobj, aclobj->local_path,
+ old_validity == NULL ? NULL :
+ &old_validity->local_validity);
+ }
if (ret <= 0)
return ret;
/* either global or local ACLs changed, need to re-read both */
acl_cache_flush(_aclobj->backend->cache, _aclobj->name);
- if (acl_backend_vfile_read_with_retry(_aclobj,
- &aclobj->global_file) < 0)
+
+ memset(&validity, 0, sizeof(validity));
+ if (acl_backend_vfile_read_with_retry(_aclobj, aclobj->global_path,
+ &validity.global_validity) < 0)
return -1;
- if (acl_backend_vfile_read_with_retry(_aclobj, &aclobj->local_file) < 0)
+ if (acl_backend_vfile_read_with_retry(_aclobj, aclobj->local_path,
+ &validity.local_validity) < 0)
return -1;
+
+ acl_cache_set_validity(_aclobj->backend->cache,
+ _aclobj->name, &validity);
return 0;
}
Index: acl-backend.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-backend.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- acl-backend.c 27 Feb 2006 16:30:39 -0000 1.1
+++ acl-backend.c 28 Feb 2006 12:38:20 -0000 1.2
@@ -46,9 +46,6 @@
backend->username = p_strdup(backend->pool, acl_username);
backend->owner_username = p_strdup(backend->pool, owner_username);
backend->group_count = group_count;
- backend->cache = acl_cache_init(backend);
- backend->aclobjs = hash_create(default_pool, backend->pool, 0,
- str_hash, (hash_cmp_callback_t *)strcmp);
storage_owner = owner_username != NULL &&
strcmp(acl_username, owner_username) == 0;
@@ -71,21 +68,10 @@
void acl_backend_deinit(struct acl_backend **_backend)
{
struct acl_backend *backend = *_backend;
- struct hash_iterate_context *iter;
- void *key, *value;
*_backend = NULL;
- iter = hash_iterate_init(backend->aclobjs);
- while (hash_iterate(iter, &key, &value)) {
- struct acl_object *aclobj = value;
-
- aclobj->backend->v.object_deinit(aclobj);
- }
- hash_iterate_deinit(iter);
-
acl_cache_deinit(&backend->cache);
- hash_destroy(backend->aclobjs);
backend->v.deinit(backend);
}
Index: acl-cache.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-cache.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- acl-cache.c 27 Feb 2006 16:30:39 -0000 1.1
+++ acl-cache.c 28 Feb 2006 12:38:20 -0000 1.2
@@ -24,6 +24,8 @@
struct acl_backend *backend;
struct hash_table *objects; /* name => struct acl_object_cache* */
+ size_t validity_rec_size;
+
/* Right names mapping is used for faster rights checking. Note that
acl_mask bitmask relies on the order to never change, so only new
rights can be added to the mapping. */
@@ -34,12 +36,16 @@
struct hash_table *right_name_idx_map;
};
-struct acl_cache *acl_cache_init(struct acl_backend *backend)
+static struct acl_mask negative_cache_entry;
+
+struct acl_cache *acl_cache_init(struct acl_backend *backend,
+ size_t validity_rec_size)
{
struct acl_cache *cache;
cache = i_new(struct acl_cache, 1);
cache->backend = backend;
+ cache->validity_rec_size = validity_rec_size;
cache->right_names_pool =
pool_alloconly_create("ACL right names", 1024);
cache->objects = hash_create(default_pool, default_pool, 0,
@@ -120,16 +126,17 @@
unsigned int idx;
void *idx_p;
char *name;
+ const char *const_name;
/* use +1 for right_name_idx_map values because we can't add NULL
values. */
idx_p = hash_lookup(cache->right_name_idx_map, right);
if (idx_p == NULL) {
/* new right name, add it */
- name = p_strdup(cache->right_names_pool, right);
+ const_name = name = p_strdup(cache->right_names_pool, right);
idx = array_count(&cache->right_idx_name_map);
- array_append(&cache->right_idx_name_map, &name, 1);
+ array_append(&cache->right_idx_name_map, &const_name, 1);
hash_insert(cache->right_name_idx_map, name,
POINTER_CAST(idx + 1));
} else {
@@ -253,17 +260,33 @@
&obj_cache->my_neg_rights[id_type]);
}
-void acl_cache_update(struct acl_cache *cache, const char *objname,
- const struct acl_rights *rights)
+static struct acl_object_cache *
+acl_cache_object_get(struct acl_cache *cache, const char *objname,
+ bool *created_r)
{
struct acl_object_cache *obj_cache;
obj_cache = hash_lookup(cache->objects, objname);
if (obj_cache == NULL) {
- obj_cache = i_new(struct acl_object_cache, 1);
+ obj_cache = i_malloc(sizeof(struct acl_object_cache) +
+ cache->validity_rec_size);
obj_cache->name = i_strdup(objname);
hash_insert(cache->objects, obj_cache->name, obj_cache);
+ *created_r = TRUE;
+ } else {
+ *created_r = FALSE;
}
+ return obj_cache;
+}
+
+void acl_cache_update(struct acl_cache *cache, const char *objname,
+ const struct acl_rights *rights)
+{
+ struct acl_object_cache *obj_cache;
+ bool created;
+
+ obj_cache = acl_cache_object_get(cache, objname, &created);
+ i_assert(obj_cache->my_current_rights != &negative_cache_entry);
switch (rights->id_type) {
case ACL_ID_ANYONE:
@@ -289,6 +312,32 @@
}
}
+void acl_cache_set_validity(struct acl_cache *cache, const char *objname,
+ const void *validity)
+{
+ struct acl_object_cache *obj_cache;
+ bool created;
+
+ obj_cache = acl_cache_object_get(cache, objname, &created);
+
+ /* @UNSAFE: validity is stored after the cache record */
+ memcpy(obj_cache + 1, validity, cache->validity_rec_size);
+
+ if (created) {
+ /* negative cache entry */
+ obj_cache->my_current_rights = &negative_cache_entry;
+ }
+}
+
+const void *acl_cache_get_validity(struct acl_cache *cache,
+ const char *objname)
+{
+ struct acl_object_cache *obj_cache;
+
+ obj_cache = hash_lookup(cache->objects, objname);
+ return obj_cache == NULL ? NULL : (obj_cache + 1);
+}
+
const char *const *acl_cache_get_names(struct acl_cache *cache,
unsigned int *count_r)
{
@@ -343,7 +392,8 @@
struct acl_object_cache *obj_cache;
obj_cache = hash_lookup(cache->objects, objname);
- if (obj_cache == NULL)
+ if (obj_cache == NULL ||
+ obj_cache->my_current_rights == &negative_cache_entry)
return NULL;
if (obj_cache->my_current_rights == NULL)
Index: acl-cache.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-cache.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- acl-cache.h 27 Feb 2006 16:30:39 -0000 1.1
+++ acl-cache.h 28 Feb 2006 12:38:20 -0000 1.2
@@ -17,7 +17,8 @@
(sizeof(pool_t) + sizeof(unsigned int) + \
(count + CHAR_BIT-1) / CHAR_BIT)
-struct acl_cache *acl_cache_init(struct acl_backend *backend);
+struct acl_cache *acl_cache_init(struct acl_backend *backend,
+ size_t validity_rec_size);
void acl_cache_deinit(struct acl_cache **cache);
struct acl_mask *acl_cache_mask_init(struct acl_cache *cache, pool_t pool,
@@ -31,9 +32,15 @@
/* Flush cache for all objects */
void acl_cache_flush_all(struct acl_cache *cache);
-/* Update object ACLs */
+/* Update object ACLs. */
void acl_cache_update(struct acl_cache *cache, const char *objname,
const struct acl_rights *rights);
+/* Update ACL object validity. */
+void acl_cache_set_validity(struct acl_cache *cache, const char *objname,
+ const void *validity);
+/* Return ACL object validity. */
+const void *acl_cache_get_validity(struct acl_cache *cache,
+ const char *objname);
/* Returns all the right names currently created. The returned pointer may
change after calling acl_cache_update(). */
Index: acl-storage.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/acl/acl-storage.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- acl-storage.c 27 Feb 2006 16:30:39 -0000 1.1
+++ acl-storage.c 28 Feb 2006 12:38:20 -0000 1.2
@@ -65,6 +65,7 @@
struct acl_mail_storage *astorage = ACL_CONTEXT(storage);
acl_backend_deinit(&astorage->backend);
+ astorage->super.destroy(storage);
}
static struct mailbox *
More information about the dovecot-cvs
mailing list