~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/plugins/quota-clone/quota-clone-plugin.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2015-05-24 15:01:19 UTC
  • mto: (4.1.53 sid)
  • mto: This revision was merged to the branch mainline in revision 102.
  • Revision ID: package-import@ubuntu.com-20150524150119-hsh6cbr1fqseapga
Tags: upstream-2.2.18
ImportĀ upstreamĀ versionĀ 2.2.18

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */
 
2
 
 
3
#include "lib.h"
 
4
#include "module-context.h"
 
5
#include "dict.h"
 
6
#include "mail-storage-private.h"
 
7
#include "quota.h"
 
8
#include "quota-clone-plugin.h"
 
9
 
 
10
#define DICT_QUOTA_CLONE_PATH DICT_PATH_PRIVATE"quota/"
 
11
#define DICT_QUOTA_CLONE_BYTES_PATH DICT_QUOTA_CLONE_PATH"storage"
 
12
#define DICT_QUOTA_CLONE_COUNT_PATH DICT_QUOTA_CLONE_PATH"messages"
 
13
 
 
14
#define QUOTA_CLONE_USER_CONTEXT(obj) \
 
15
        MODULE_CONTEXT(obj, quota_clone_user_module)
 
16
#define QUOTA_CLONE_CONTEXT(obj) \
 
17
        MODULE_CONTEXT(obj, quota_clone_storage_module)
 
18
 
 
19
static MODULE_CONTEXT_DEFINE_INIT(quota_clone_user_module,
 
20
                                  &mail_user_module_register);
 
21
static MODULE_CONTEXT_DEFINE_INIT(quota_clone_storage_module,
 
22
                                  &mail_storage_module_register);
 
23
 
 
24
struct quota_clone_user {
 
25
        union mail_user_module_context module_ctx;
 
26
        struct dict *dict;
 
27
};
 
28
 
 
29
struct quota_clone_mailbox {
 
30
        union mailbox_module_context module_ctx;
 
31
        bool quota_changed;
 
32
};
 
33
 
 
34
static void quota_clone_flush(struct mailbox *box)
 
35
{
 
36
        struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
 
37
        struct quota_clone_user *quser =
 
38
                QUOTA_CLONE_USER_CONTEXT(box->storage->user);
 
39
        struct dict_transaction_context *trans;
 
40
        struct quota_root_iter *iter;
 
41
        struct quota_root *root;
 
42
        uint64_t value, limit;
 
43
        int ret;
 
44
 
 
45
        /* we'll clone the first quota root */
 
46
        iter = quota_root_iter_init(box);
 
47
        root = quota_root_iter_next(iter);
 
48
        if (root == NULL) {
 
49
                /* no quota roots defined for this mailbox - ignore */
 
50
                qbox->quota_changed = FALSE;
 
51
                return;
 
52
        }
 
53
        quota_root_iter_deinit(&iter);
 
54
 
 
55
        trans = dict_transaction_begin(quser->dict);
 
56
        /* update bytes */
 
57
        ret = quota_get_resource(root, "", QUOTA_NAME_STORAGE_BYTES,
 
58
                                 &value, &limit);
 
59
        if (ret < 0)
 
60
                i_error("quota_clone_plugin: Failed to lookup current quota bytes");
 
61
        else {
 
62
                dict_set(trans, DICT_QUOTA_CLONE_BYTES_PATH,
 
63
                         t_strdup_printf("%llu", (unsigned long long)value));
 
64
        }
 
65
        /* update messages */
 
66
        ret = quota_get_resource(root, "", QUOTA_NAME_MESSAGES,
 
67
                                 &value, &limit);
 
68
        if (ret < 0)
 
69
                i_error("quota_clone_plugin: Failed to lookup current quota count");
 
70
        else {
 
71
                dict_set(trans, DICT_QUOTA_CLONE_COUNT_PATH,
 
72
                         t_strdup_printf("%llu", (unsigned long long)value));
 
73
        }
 
74
        if (dict_transaction_commit(&trans) < 0)
 
75
                i_error("quota_clone_plugin: Failed to commit dict update");
 
76
        else
 
77
                qbox->quota_changed = FALSE;
 
78
}
 
79
 
 
80
static int quota_clone_save_finish(struct mail_save_context *ctx)
 
81
{
 
82
        struct quota_clone_mailbox *qbox =
 
83
                QUOTA_CLONE_CONTEXT(ctx->transaction->box);
 
84
 
 
85
        qbox->quota_changed = TRUE;
 
86
        return qbox->module_ctx.super.save_finish(ctx);
 
87
}
 
88
 
 
89
static int
 
90
quota_clone_copy(struct mail_save_context *ctx, struct mail *mail)
 
91
{
 
92
        struct quota_clone_mailbox *qbox =
 
93
                QUOTA_CLONE_CONTEXT(ctx->transaction->box);
 
94
 
 
95
        qbox->quota_changed = TRUE;
 
96
        return qbox->module_ctx.super.copy(ctx, mail);
 
97
}
 
98
 
 
99
static void
 
100
quota_clone_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
 
101
                                enum mailbox_sync_type sync_type)
 
102
{
 
103
        struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
 
104
 
 
105
        if (qbox->module_ctx.super.sync_notify != NULL)
 
106
                qbox->module_ctx.super.sync_notify(box, uid, sync_type);
 
107
 
 
108
        if (sync_type == MAILBOX_SYNC_TYPE_EXPUNGE)
 
109
                qbox->quota_changed = TRUE;
 
110
}
 
111
 
 
112
static void quota_clone_mailbox_close(struct mailbox *box)
 
113
{
 
114
        struct quota_clone_mailbox *qbox = QUOTA_CLONE_CONTEXT(box);
 
115
 
 
116
        qbox->module_ctx.super.close(box);
 
117
        if (qbox->quota_changed)
 
118
                quota_clone_flush(box);
 
119
}
 
120
 
 
121
static void quota_clone_mailbox_allocated(struct mailbox *box)
 
122
{
 
123
        struct quota_clone_user *quser =
 
124
                QUOTA_CLONE_USER_CONTEXT(box->storage->user);
 
125
        struct mailbox_vfuncs *v = box->vlast;
 
126
        struct quota_clone_mailbox *qbox;
 
127
 
 
128
        if (quser == NULL)
 
129
                return;
 
130
 
 
131
        qbox = p_new(box->pool, struct quota_clone_mailbox, 1);
 
132
        qbox->module_ctx.super = *v;
 
133
        box->vlast = &qbox->module_ctx.super;
 
134
 
 
135
        v->save_finish = quota_clone_save_finish;
 
136
        v->copy = quota_clone_copy;
 
137
        v->sync_notify = quota_clone_mailbox_sync_notify;
 
138
        v->close = quota_clone_mailbox_close;
 
139
        MODULE_CONTEXT_SET(box, quota_clone_storage_module, qbox);
 
140
}
 
141
 
 
142
static void quota_clone_mail_user_deinit(struct mail_user *user)
 
143
{
 
144
        struct quota_clone_user *quser = QUOTA_CLONE_USER_CONTEXT(user);
 
145
 
 
146
        dict_deinit(&quser->dict);
 
147
        quser->module_ctx.super.deinit(user);
 
148
}
 
149
 
 
150
static void quota_clone_mail_user_created(struct mail_user *user)
 
151
{
 
152
        struct quota_clone_user *quser;
 
153
        struct mail_user_vfuncs *v = user->vlast;
 
154
        struct dict_settings dict_set;
 
155
        struct dict *dict;
 
156
        const char *uri, *error;
 
157
 
 
158
        uri = mail_user_plugin_getenv(user, "quota_clone_dict");
 
159
        if (uri == NULL || uri[0] == '\0') {
 
160
                i_error("The quota_clone_dict setting is missing from configuration");
 
161
                return;
 
162
        }
 
163
 
 
164
        memset(&dict_set, 0, sizeof(dict_set));
 
165
        dict_set.username = user->username;
 
166
        dict_set.base_dir = user->set->base_dir;
 
167
        (void)mail_user_get_home(user, &dict_set.home_dir);
 
168
        if (dict_init_full(uri, &dict_set, &dict, &error) < 0) {
 
169
                i_error("quota_clone_dict: Failed to initialize '%s': %s",
 
170
                        uri, error);
 
171
                return;
 
172
        }
 
173
 
 
174
        quser = p_new(user->pool, struct quota_clone_user, 1);
 
175
        quser->module_ctx.super = *v;
 
176
        user->vlast = &quser->module_ctx.super;
 
177
        v->deinit = quota_clone_mail_user_deinit;
 
178
        quser->dict = dict;
 
179
        MODULE_CONTEXT_SET(user, quota_clone_user_module, quser);
 
180
}
 
181
 
 
182
static struct mail_storage_hooks quota_clone_mail_storage_hooks = {
 
183
        .mailbox_allocated = quota_clone_mailbox_allocated,
 
184
        .mail_user_created = quota_clone_mail_user_created
 
185
};
 
186
 
 
187
void quota_clone_plugin_init(struct module *module ATTR_UNUSED)
 
188
{
 
189
        mail_storage_hooks_add(module, &quota_clone_mail_storage_hooks);
 
190
}
 
191
 
 
192
void quota_clone_plugin_deinit(void)
 
193
{
 
194
        mail_storage_hooks_remove(&quota_clone_mail_storage_hooks);
 
195
}
 
196
 
 
197
const char *quota_clone_plugin_dependencies[] = { "quota", NULL };