comparison src/plugins/imap-quota/imap-quota-plugin.c @ 9564:efe0efc22d22 HEAD

imap-quota: Iterate quota roots only once when replying to GETQUOTAROOT. This halves the required dict lookup count.
author Timo Sirainen <tss@iki.fi>
date Tue, 20 Apr 2010 13:02:29 +0300
parents 00cd9aacd03c
children
comparison
equal deleted inserted replaced
9563:002b58bab1f5 9564:efe0efc22d22
1 /* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */ 1 /* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
2 2
3 #include "common.h" 3 #include "common.h"
4 #include "str.h" 4 #include "str.h"
5 #include "ostream.h"
5 #include "imap-quote.h" 6 #include "imap-quote.h"
6 #include "mail-namespace.h" 7 #include "mail-namespace.h"
7 #include "commands.h" 8 #include "commands.h"
8 #include "quota.h" 9 #include "quota.h"
9 #include "quota-plugin.h" 10 #include "quota-plugin.h"
27 return t_strdup_printf("%s%c%s", owner->username, 28 return t_strdup_printf("%s%c%s", owner->username,
28 QUOTA_USER_SEPARATOR, name); 29 QUOTA_USER_SEPARATOR, name);
29 } 30 }
30 31
31 static void 32 static void
32 quota_send(struct client_command_context *cmd, struct mail_user *owner, 33 quota_reply_write(string_t *str, struct mail_user *user,
33 struct quota_root *root) 34 struct mail_user *owner, struct quota_root *root)
34 { 35 {
35 const char *name, *const *list; 36 const char *name, *const *list;
36 string_t *str;
37 unsigned int i; 37 unsigned int i;
38 uint64_t value, limit; 38 uint64_t value, limit;
39 int ret; 39 int ret = 0;
40 40
41 str = t_str_new(128);
42 str_append(str, "* QUOTA "); 41 str_append(str, "* QUOTA ");
43 name = imap_quota_root_get_name(cmd->client->user, owner, root); 42 name = imap_quota_root_get_name(user, owner, root);
44 imap_quote_append_string(str, name, FALSE); 43 imap_quote_append_string(str, name, FALSE);
45 44
46 str_append(str, " ("); 45 str_append(str, " (");
47 list = quota_root_get_resources(root); 46 list = quota_root_get_resources(root);
48 for (i = 0; *list != NULL; list++) { 47 for (i = 0; *list != NULL; list++) {
49 ret = quota_get_resource(root, "", *list, &value, &limit); 48 ret = quota_get_resource(root, "", *list, &value, &limit);
49 if (ret < 0)
50 break;
50 if (ret > 0) { 51 if (ret > 0) {
51 if (i > 0) 52 if (i > 0)
52 str_append_c(str, ' '); 53 str_append_c(str, ' ');
53 str_printfa(str, "%s %llu %llu", *list, 54 str_printfa(str, "%s %llu %llu", *list,
54 (unsigned long long)value, 55 (unsigned long long)value,
55 (unsigned long long)limit); 56 (unsigned long long)limit);
56 i++; 57 i++;
57 } else if (ret < 0) { 58 }
58 client_send_line(cmd->client, 59 }
59 "* BAD Internal quota calculation error"); 60 str_append(str, ")\r\n");
60 } 61
61 } 62 if (ret < 0)
62 str_append_c(str, ')'); 63 str_append(str, "* BAD Internal quota calculation error\r\n");
63 client_send_line(cmd->client, str_c(str));
64 } 64 }
65 65
66 static bool cmd_getquotaroot(struct client_command_context *cmd) 66 static bool cmd_getquotaroot(struct client_command_context *cmd)
67 { 67 {
68 struct client *client = cmd->client; 68 struct client *client = cmd->client;
70 struct mail_namespace *ns; 70 struct mail_namespace *ns;
71 struct mailbox *box; 71 struct mailbox *box;
72 struct quota_root_iter *iter; 72 struct quota_root_iter *iter;
73 struct quota_root *root; 73 struct quota_root *root;
74 const char *orig_mailbox, *mailbox, *name; 74 const char *orig_mailbox, *mailbox, *name;
75 string_t *str; 75 string_t *quotaroot_reply, *quota_reply;
76 76
77 /* <mailbox> */ 77 /* <mailbox> */
78 if (!client_read_string_args(cmd, 1, &mailbox)) 78 if (!client_read_string_args(cmd, 1, &mailbox))
79 return FALSE; 79 return FALSE;
80 80
102 mailbox_close(&box); 102 mailbox_close(&box);
103 client_send_tagline(cmd, "NO Not showing other users' quota."); 103 client_send_tagline(cmd, "NO Not showing other users' quota.");
104 return TRUE; 104 return TRUE;
105 } 105 }
106 106
107 /* send QUOTAROOT reply */ 107 /* build QUOTAROOT reply and QUOTA reply for all quota roots */
108 str = t_str_new(128); 108 quotaroot_reply = t_str_new(128);
109 str_append(str, "* QUOTAROOT "); 109 quota_reply = t_str_new(256);
110 imap_quote_append_string(str, orig_mailbox, FALSE); 110 str_append(quotaroot_reply, "* QUOTAROOT ");
111 imap_quote_append_string(quotaroot_reply, mailbox, FALSE);
111 112
112 iter = quota_root_iter_init(box); 113 iter = quota_root_iter_init(box);
113 while ((root = quota_root_iter_next(iter)) != NULL) { 114 while ((root = quota_root_iter_next(iter)) != NULL) {
114 str_append_c(str, ' '); 115 str_append_c(quotaroot_reply, ' ');
115 name = imap_quota_root_get_name(client->user, ns->owner, root); 116 name = imap_quota_root_get_name(client->user, ns->owner, root);
116 imap_quote_append_string(str, name, FALSE); 117 imap_quote_append_string(quotaroot_reply, name, FALSE);
117 } 118
118 quota_root_iter_deinit(&iter); 119 quota_reply_write(quota_reply, client->user, ns->owner, root);
119 client_send_line(client, str_c(str)); 120 }
120
121 /* send QUOTA reply for each quotaroot */
122 iter = quota_root_iter_init(box);
123 while ((root = quota_root_iter_next(iter)) != NULL)
124 quota_send(cmd, ns->owner, root);
125 quota_root_iter_deinit(&iter); 121 quota_root_iter_deinit(&iter);
126 mailbox_close(&box); 122 mailbox_close(&box);
127 123
124 /* send replies */
125 client_send_line(client, str_c(quotaroot_reply));
126 o_stream_send(client->output, str_data(quota_reply),
127 str_len(quota_reply));
128 client_send_tagline(cmd, "OK Getquotaroot completed."); 128 client_send_tagline(cmd, "OK Getquotaroot completed.");
129 return TRUE; 129 return TRUE;
130 } 130 }
131 131
132 static bool cmd_getquota(struct client_command_context *cmd) 132 static bool cmd_getquota(struct client_command_context *cmd)
133 { 133 {
134 struct mail_user *owner = cmd->client->user; 134 struct mail_user *owner = cmd->client->user;
135 struct quota_root *root; 135 struct quota_root *root;
136 const char *root_name, *p; 136 const char *root_name, *p;
137 string_t *quota_reply;
137 138
138 /* <quota root> */ 139 /* <quota root> */
139 if (!client_read_string_args(cmd, 1, &root_name)) 140 if (!client_read_string_args(cmd, 1, &root_name))
140 return FALSE; 141 return FALSE;
141 142
159 if (root == NULL) { 160 if (root == NULL) {
160 client_send_tagline(cmd, "NO Quota root doesn't exist."); 161 client_send_tagline(cmd, "NO Quota root doesn't exist.");
161 return TRUE; 162 return TRUE;
162 } 163 }
163 164
164 quota_send(cmd, owner, root); 165 quota_reply = t_str_new(128);
166 quota_reply_write(quota_reply, cmd->client->user, owner, root);
167 o_stream_send(cmd->client->output, str_data(quota_reply),
168 str_len(quota_reply));
169
165 client_send_tagline(cmd, "OK Getquota completed."); 170 client_send_tagline(cmd, "OK Getquota completed.");
166 return TRUE; 171 return TRUE;
167 } 172 }
168 173
169 static bool cmd_setquota(struct client_command_context *cmd) 174 static bool cmd_setquota(struct client_command_context *cmd)