Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/lib-dict/dict-client.c @ 6142:6c0bfc35af03 HEAD
Removed memory pool parameter from iostreams. Default pool was almost always
used, and the stream usually required destroying anyway so it didn't even
make freeing memory easier.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 24 Jul 2007 06:59:56 +0300 |
parents | 4be4c887deb7 |
children | c62f7ee79446 |
rev | line source |
---|---|
3793 | 1 /* Copyright (C) 2005 Timo Sirainen */ |
2 | |
3 #include "lib.h" | |
4 #include "str.h" | |
5 #include "network.h" | |
6 #include "istream.h" | |
7 #include "ostream.h" | |
8 #include "dict-private.h" | |
9 #include "dict-client.h" | |
10 | |
11 #include <unistd.h> | |
12 #include <fcntl.h> | |
13 | |
14 struct client_dict { | |
15 struct dict dict; | |
16 | |
17 pool_t pool; | |
18 int fd; | |
19 const char *uri; | |
20 const char *username; | |
21 const char *path; | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
22 enum dict_data_type value_type; |
3793 | 23 |
24 struct istream *input; | |
25 struct ostream *output; | |
26 | |
27 unsigned int connect_counter; | |
28 unsigned int transaction_id_counter; | |
29 | |
30 unsigned int in_iteration:1; | |
31 unsigned int handshaked:1; | |
32 }; | |
33 | |
34 struct client_dict_iterate_context { | |
35 struct dict_iterate_context ctx; | |
36 | |
37 pool_t pool; | |
3863
55df57c028d4
Added "bool" type and changed all ints that were used as booleans to bool.
Timo Sirainen <tss@iki.fi>
parents:
3858
diff
changeset
|
38 bool failed; |
3793 | 39 }; |
40 | |
41 struct client_dict_transaction_context { | |
42 struct dict_transaction_context ctx; | |
43 | |
44 unsigned int id; | |
45 unsigned int connect_counter; | |
46 | |
4512
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
47 unsigned int failed:1; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
48 unsigned int sent_begin:1; |
3793 | 49 }; |
50 | |
51 static int client_dict_connect(struct client_dict *dict); | |
52 static void client_dict_disconnect(struct client_dict *dict); | |
53 | |
54 const char *dict_client_escape(const char *src) | |
55 { | |
56 const char *p; | |
57 string_t *dest; | |
58 | |
59 /* first do a quick lookup to see if there's anything to escape. | |
60 probably not. */ | |
61 for (p = src; *p != '\0'; p++) { | |
62 if (*p == '\t' || *p == '\n' || *p == '\001') | |
63 break; | |
64 } | |
65 | |
66 if (*p == '\0') | |
67 return src; | |
68 | |
69 dest = t_str_new(256); | |
70 str_append_n(dest, src, p - src); | |
71 | |
3858 | 72 for (; *p != '\0'; p++) { |
3793 | 73 switch (*p) { |
74 case '\t': | |
75 str_append_c(dest, '\001'); | |
76 str_append_c(dest, 't'); | |
77 break; | |
78 case '\n': | |
79 str_append_c(dest, '\001'); | |
80 str_append_c(dest, 'n'); | |
81 break; | |
82 case '\001': | |
83 str_append_c(dest, '\001'); | |
84 str_append_c(dest, '1'); | |
85 break; | |
86 default: | |
87 str_append_c(dest, *p); | |
88 break; | |
89 } | |
90 } | |
91 return str_c(dest); | |
92 } | |
93 | |
94 const char *dict_client_unescape(const char *src) | |
95 { | |
96 const char *p; | |
97 string_t *dest; | |
98 | |
99 /* first do a quick lookup to see if there's anything to unescape. | |
100 probably not. */ | |
101 for (p = src; *p != '\0'; p++) { | |
102 if (*p == '\001') | |
103 break; | |
104 } | |
105 | |
106 if (*p == '\0') | |
107 return src; | |
108 | |
109 dest = t_str_new(256); | |
110 str_append_n(dest, src, p - src); | |
111 for (; *p != '\0'; p++) { | |
112 if (*p != '\001') | |
113 str_append_c(dest, *p); | |
114 else if (p[1] != '\0') { | |
115 p++; | |
116 switch (*p) { | |
117 case '1': | |
118 str_append_c(dest, '\001'); | |
119 break; | |
120 case 't': | |
121 str_append_c(dest, '\t'); | |
122 break; | |
123 case 'n': | |
124 str_append_c(dest, '\n'); | |
125 break; | |
126 } | |
127 } | |
128 } | |
129 return str_c(dest); | |
130 } | |
131 | |
132 static int client_dict_send_query(struct client_dict *dict, const char *query) | |
133 { | |
4368 | 134 if (dict->output == NULL) { |
135 /* not connected currently */ | |
136 if (client_dict_connect(dict) < 0) | |
137 return -1; | |
138 } | |
139 | |
3793 | 140 if (o_stream_send_str(dict->output, query) < 0 || |
141 o_stream_flush(dict->output) < 0) { | |
142 /* Send failed */ | |
143 if (!dict->handshaked) { | |
144 /* we're trying to send hello, don't try to reconnect */ | |
145 return -1; | |
146 } | |
147 | |
148 /* Reconnect and try again. */ | |
149 client_dict_disconnect(dict); | |
150 if (client_dict_connect(dict) < 0) | |
151 return -1; | |
152 | |
153 if (o_stream_send_str(dict->output, query) < 0 || | |
154 o_stream_flush(dict->output) < 0) { | |
155 i_error("write(%s) failed: %m", dict->path); | |
156 return -1; | |
157 } | |
158 } | |
159 return 0; | |
160 } | |
161 | |
4368 | 162 static int |
4512
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
163 client_dict_transaction_send_begin(struct client_dict_transaction_context *ctx) |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
164 { |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
165 struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
166 const char *query; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
167 |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
168 if (ctx->failed) |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
169 return -1; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
170 |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
171 t_push(); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
172 query = t_strdup_printf("%c%u\n", DICT_PROTOCOL_CMD_BEGIN, ctx->id); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
173 if (client_dict_send_query(dict, query) < 0) |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
174 ctx->failed = TRUE; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
175 else |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
176 ctx->connect_counter = dict->connect_counter; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
177 t_pop(); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
178 |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
179 return ctx->failed ? -1 : 0; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
180 } |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
181 |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
182 static int |
4368 | 183 client_dict_send_transaction_query(struct client_dict_transaction_context *ctx, |
184 const char *query) | |
185 { | |
186 struct client_dict *dict = (struct client_dict *)ctx->ctx.dict; | |
187 | |
4512
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
188 if (!ctx->sent_begin) { |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
189 if (client_dict_transaction_send_begin(ctx) < 0) |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
190 return -1; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
191 ctx->sent_begin = TRUE; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
192 } |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
193 |
4385 | 194 if (ctx->connect_counter != dict->connect_counter || ctx->failed) |
195 return -1; | |
196 | |
197 if (dict->output == NULL) { | |
4512
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
198 /* not connected, this'll fail */ |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
199 return -1; |
4385 | 200 } |
201 | |
4368 | 202 if (o_stream_send_str(dict->output, query) < 0 || |
203 o_stream_flush(dict->output) < 0) { | |
204 /* Send failed. Our transactions have died, so don't even try | |
205 to re-send the command */ | |
206 ctx->failed = TRUE; | |
207 client_dict_disconnect(dict); | |
208 return -1; | |
209 } | |
210 return 0; | |
211 } | |
212 | |
3793 | 213 static char *client_dict_read_line(struct client_dict *dict) |
214 { | |
215 char *line; | |
216 int ret; | |
217 | |
4519
4be4c887deb7
dict proxy: Dictionary iteration was broken.
Timo Sirainen <tss@iki.fi>
parents:
4517
diff
changeset
|
218 line = i_stream_next_line(dict->input); |
4be4c887deb7
dict proxy: Dictionary iteration was broken.
Timo Sirainen <tss@iki.fi>
parents:
4517
diff
changeset
|
219 if (line != NULL) |
4be4c887deb7
dict proxy: Dictionary iteration was broken.
Timo Sirainen <tss@iki.fi>
parents:
4517
diff
changeset
|
220 return line; |
4be4c887deb7
dict proxy: Dictionary iteration was broken.
Timo Sirainen <tss@iki.fi>
parents:
4517
diff
changeset
|
221 |
3793 | 222 while ((ret = i_stream_read(dict->input)) > 0) { |
223 line = i_stream_next_line(dict->input); | |
224 if (line != NULL) | |
225 return line; | |
226 } | |
227 | |
228 i_error("read(%s) failed: %m", dict->path); | |
229 return NULL; | |
230 } | |
231 | |
232 static int client_dict_connect(struct client_dict *dict) | |
233 { | |
234 const char *query; | |
235 | |
236 i_assert(dict->fd == -1); | |
237 | |
238 dict->fd = net_connect_unix(dict->path); | |
239 if (dict->fd == -1) { | |
240 i_error("net_connect_unix(%s) failed: %m", dict->path); | |
241 return -1; | |
242 } | |
243 | |
244 /* Dictionary lookups are blocking */ | |
245 net_set_nonblock(dict->fd, FALSE); | |
246 | |
6142
6c0bfc35af03
Removed memory pool parameter from iostreams. Default pool was almost always
Timo Sirainen <tss@iki.fi>
parents:
4519
diff
changeset
|
247 dict->input = i_stream_create_file(dict->fd, (size_t)-1, FALSE); |
6c0bfc35af03
Removed memory pool parameter from iostreams. Default pool was almost always
Timo Sirainen <tss@iki.fi>
parents:
4519
diff
changeset
|
248 dict->output = o_stream_create_file(dict->fd, 4096, FALSE); |
3793 | 249 dict->transaction_id_counter = 0; |
250 | |
251 t_push(); | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
252 query = t_strdup_printf("%c%u\t%u\t%d\t%s\t%s\n", |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
253 DICT_PROTOCOL_CMD_HELLO, |
3793 | 254 DICT_CLIENT_PROTOCOL_MAJOR_VERSION, |
255 DICT_CLIENT_PROTOCOL_MINOR_VERSION, | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
256 dict->value_type, dict->username, dict->uri); |
3793 | 257 if (client_dict_send_query(dict, query) < 0) { |
258 client_dict_disconnect(dict); | |
4367
763401b5b344
t_pop() calls were missing from some error handling paths
Timo Sirainen <tss@iki.fi>
parents:
4070
diff
changeset
|
259 t_pop(); |
3793 | 260 return -1; |
261 } | |
262 t_pop(); | |
263 | |
264 dict->handshaked = TRUE; | |
265 return 0; | |
266 } | |
267 | |
268 static void client_dict_disconnect(struct client_dict *dict) | |
269 { | |
270 dict->connect_counter++; | |
271 dict->handshaked = FALSE; | |
272 | |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3863
diff
changeset
|
273 if (dict->input != NULL) |
4070
71b8faa84ec6
Added i_stream_destroy() and o_stream_destroy() and used them instead of
Timo Sirainen <tss@iki.fi>
parents:
3990
diff
changeset
|
274 i_stream_destroy(&dict->input); |
3879
928229f8b3e6
deinit, unref, destroy, close, free, etc. functions now take a pointer to
Timo Sirainen <tss@iki.fi>
parents:
3863
diff
changeset
|
275 if (dict->output != NULL) |
4070
71b8faa84ec6
Added i_stream_destroy() and o_stream_destroy() and used them instead of
Timo Sirainen <tss@iki.fi>
parents:
3990
diff
changeset
|
276 o_stream_destroy(&dict->output); |
3793 | 277 |
278 if (dict->fd != -1) { | |
279 if (close(dict->fd) < 0) | |
280 i_error("close(%s) failed: %m", dict->path); | |
281 dict->fd = -1; | |
282 } | |
283 } | |
284 | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
285 static struct dict * |
4517
e661182eab75
Berkeley DB dict support is now enabled only when using --with-db configure option.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4516
diff
changeset
|
286 client_dict_init(struct dict *driver, const char *uri, |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
287 enum dict_data_type value_type, const char *username) |
3793 | 288 { |
289 struct client_dict *dict; | |
3967
6fabe878c46d
Dictionary takes now a username parameter, which is used for private
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
290 const char *dest_uri; |
3793 | 291 pool_t pool; |
292 | |
3967
6fabe878c46d
Dictionary takes now a username parameter, which is used for private
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
293 /* uri = [<path>] ":" <uri> */ |
3793 | 294 dest_uri = strchr(uri, ':'); |
295 if (dest_uri == NULL) { | |
296 i_error("dict-client: Invalid URI: %s", uri); | |
297 return NULL; | |
298 } | |
299 | |
300 pool = pool_alloconly_create("client dict", 1024); | |
301 dict = p_new(pool, struct client_dict, 1); | |
302 dict->pool = pool; | |
4517
e661182eab75
Berkeley DB dict support is now enabled only when using --with-db configure option.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4516
diff
changeset
|
303 dict->dict = *driver; |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
304 dict->value_type = value_type; |
3967
6fabe878c46d
Dictionary takes now a username parameter, which is used for private
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
305 dict->username = p_strdup(pool, username); |
3793 | 306 |
307 dict->fd = -1; | |
308 | |
3967
6fabe878c46d
Dictionary takes now a username parameter, which is used for private
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
309 if (*uri != ':') { |
3793 | 310 /* path given */ |
3967
6fabe878c46d
Dictionary takes now a username parameter, which is used for private
Timo Sirainen <tss@iki.fi>
parents:
3879
diff
changeset
|
311 dict->path = p_strdup_until(pool, uri, dest_uri); |
3793 | 312 } else { |
313 dict->path = DEFAULT_DICT_SERVER_SOCKET_PATH; | |
314 } | |
315 dict->uri = p_strdup(pool, dest_uri + 1); | |
316 | |
317 (void)client_dict_connect(dict); | |
318 return &dict->dict; | |
319 } | |
320 | |
321 static void client_dict_deinit(struct dict *_dict) | |
322 { | |
323 struct client_dict *dict = (struct client_dict *)_dict; | |
324 | |
325 client_dict_disconnect(dict); | |
326 pool_unref(dict->pool); | |
327 } | |
328 | |
329 static int client_dict_lookup(struct dict *_dict, pool_t pool, | |
330 const char *key, const char **value_r) | |
331 { | |
332 struct client_dict *dict = (struct client_dict *)_dict; | |
333 const char *line; | |
334 | |
335 if (dict->fd == -1) | |
336 return -1; | |
337 | |
338 t_push(); | |
339 line = t_strdup_printf("%c%s\n", DICT_PROTOCOL_CMD_LOOKUP, | |
340 dict_client_escape(key)); | |
341 if (client_dict_send_query(dict, line) < 0) { | |
342 t_pop(); | |
343 return -1; | |
344 } | |
345 t_pop(); | |
346 | |
347 /* read reply */ | |
348 line = client_dict_read_line(dict); | |
349 if (line == NULL) | |
350 return -1; | |
351 | |
352 if (*line == DICT_PROTOCOL_REPLY_OK) { | |
353 *value_r = p_strdup(pool, dict_client_unescape(line + 1)); | |
354 return 1; | |
355 } else { | |
356 *value_r = NULL; | |
357 return *line == DICT_PROTOCOL_REPLY_NOTFOUND ? 0 : -1; | |
358 } | |
359 } | |
360 | |
361 static struct dict_iterate_context * | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
362 client_dict_iterate_init(struct dict *_dict, const char *path, |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
363 enum dict_iterate_flags flags) |
3793 | 364 { |
365 struct client_dict *dict = (struct client_dict *)_dict; | |
366 struct client_dict_iterate_context *ctx; | |
367 const char *query; | |
368 | |
369 if (dict->in_iteration) | |
370 i_panic("dict-client: Only one iteration supported"); | |
371 dict->in_iteration = TRUE; | |
372 | |
373 ctx = i_new(struct client_dict_iterate_context, 1); | |
374 ctx->ctx.dict = _dict; | |
375 ctx->pool = pool_alloconly_create("client dict iteration", 512); | |
376 | |
377 t_push(); | |
378 query = t_strdup_printf("%c%d\t%s\n", DICT_PROTOCOL_CMD_ITERATE, | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
379 flags, dict_client_escape(path)); |
3793 | 380 if (client_dict_send_query(dict, query) < 0) |
381 ctx->failed = TRUE; | |
382 t_pop(); | |
383 | |
384 return &ctx->ctx; | |
385 } | |
386 | |
387 static int client_dict_iterate(struct dict_iterate_context *_ctx, | |
388 const char **key_r, const char **value_r) | |
389 { | |
390 struct client_dict_iterate_context *ctx = | |
391 (struct client_dict_iterate_context *)_ctx; | |
392 struct client_dict *dict = (struct client_dict *)_ctx->dict; | |
393 char *line, *value; | |
394 | |
395 if (ctx->failed) | |
396 return -1; | |
397 | |
398 /* read next reply */ | |
399 line = client_dict_read_line(dict); | |
400 if (line == NULL) | |
401 return -1; | |
402 | |
403 if (*line == '\0') { | |
404 /* end of iteration */ | |
405 return 0; | |
406 } | |
407 | |
408 /* line contains key \t value */ | |
409 p_clear(ctx->pool); | |
410 | |
411 value = strchr(line, '\t'); | |
412 if (value == NULL) { | |
413 /* broken protocol */ | |
414 i_error("dict client (%s) sent broken reply", dict->path); | |
415 return -1; | |
416 } | |
417 *value++ = '\0'; | |
418 | |
419 *key_r = p_strdup(ctx->pool, dict_client_unescape(line)); | |
420 *value_r = p_strdup(ctx->pool, dict_client_unescape(value)); | |
421 return 1; | |
422 } | |
423 | |
424 static void client_dict_iterate_deinit(struct dict_iterate_context *_ctx) | |
425 { | |
426 struct client_dict *dict = (struct client_dict *)_ctx->dict; | |
427 struct client_dict_iterate_context *ctx = | |
428 (struct client_dict_iterate_context *)_ctx; | |
429 | |
430 pool_unref(ctx->pool); | |
431 i_free(ctx); | |
432 dict->in_iteration = TRUE; | |
433 } | |
434 | |
435 static struct dict_transaction_context * | |
436 client_dict_transaction_init(struct dict *_dict) | |
437 { | |
438 struct client_dict *dict = (struct client_dict *)_dict; | |
439 struct client_dict_transaction_context *ctx; | |
440 | |
441 ctx = i_new(struct client_dict_transaction_context, 1); | |
442 ctx->ctx.dict = _dict; | |
443 ctx->id = ++dict->transaction_id_counter; | |
4368 | 444 |
3793 | 445 return &ctx->ctx; |
446 } | |
447 | |
448 static int client_dict_transaction_commit(struct dict_transaction_context *_ctx) | |
449 { | |
450 struct client_dict_transaction_context *ctx = | |
451 (struct client_dict_transaction_context *)_ctx; | |
452 struct client_dict *dict = (struct client_dict *)_ctx->dict; | |
453 const char *query, *line; | |
454 int ret = ctx->failed ? -1 : 0; | |
455 | |
4512
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
456 if (ctx->sent_begin) { |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
457 t_push(); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
458 query = t_strdup_printf("%c%u\n", !ctx->failed ? |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
459 DICT_PROTOCOL_CMD_COMMIT : |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
460 DICT_PROTOCOL_CMD_ROLLBACK, ctx->id); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
461 if (client_dict_send_transaction_query(ctx, query) < 0) |
3793 | 462 ret = -1; |
4512
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
463 else if (ret == 0) { |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
464 /* read reply */ |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
465 line = client_dict_read_line(dict); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
466 if (line == NULL || *line != DICT_PROTOCOL_REPLY_OK) |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
467 ret = -1; |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
468 } |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
469 t_pop(); |
4385 | 470 } |
3793 | 471 |
472 i_free(ctx); | |
473 return ret; | |
474 } | |
475 | |
476 static void | |
477 client_dict_transaction_rollback(struct dict_transaction_context *_ctx) | |
478 { | |
479 struct client_dict_transaction_context *ctx = | |
480 (struct client_dict_transaction_context *)_ctx; | |
481 const char *query; | |
482 | |
4512
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
483 if (ctx->sent_begin) { |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
484 t_push(); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
485 query = t_strdup_printf("%c%u\n", DICT_PROTOCOL_CMD_ROLLBACK, |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
486 ctx->id); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
487 (void)client_dict_send_transaction_query(ctx, query); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
488 t_pop(); |
b5d4c1e9a492
Delay sending the transaction begin command to server until the first
Timo Sirainen <tss@iki.fi>
parents:
4385
diff
changeset
|
489 } |
4385 | 490 |
3793 | 491 i_free(ctx); |
492 } | |
493 | |
494 static void client_dict_set(struct dict_transaction_context *_ctx, | |
495 const char *key, const char *value) | |
496 { | |
497 struct client_dict_transaction_context *ctx = | |
498 (struct client_dict_transaction_context *)_ctx; | |
499 const char *query; | |
500 | |
501 t_push(); | |
3990
e2e6919c6c4d
LF wasn't sent at the end of all commands.
Timo Sirainen <tss@iki.fi>
parents:
3967
diff
changeset
|
502 query = t_strdup_printf("%c%u\t%s\t%s\n", |
e2e6919c6c4d
LF wasn't sent at the end of all commands.
Timo Sirainen <tss@iki.fi>
parents:
3967
diff
changeset
|
503 DICT_PROTOCOL_CMD_SET, ctx->id, |
3793 | 504 dict_client_escape(key), |
505 dict_client_escape(value)); | |
4368 | 506 (void)client_dict_send_transaction_query(ctx, query); |
3793 | 507 t_pop(); |
508 } | |
509 | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
510 static void client_dict_unset(struct dict_transaction_context *_ctx, |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
511 const char *key) |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
512 { |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
513 struct client_dict_transaction_context *ctx = |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
514 (struct client_dict_transaction_context *)_ctx; |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
515 const char *query; |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
516 |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
517 t_push(); |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
518 query = t_strdup_printf("%c%u\t%s\n", |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
519 DICT_PROTOCOL_CMD_UNSET, ctx->id, |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
520 dict_client_escape(key)); |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
521 (void)client_dict_send_transaction_query(ctx, query); |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
522 t_pop(); |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
523 } |
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
524 |
3793 | 525 static void client_dict_atomic_inc(struct dict_transaction_context *_ctx, |
3990
e2e6919c6c4d
LF wasn't sent at the end of all commands.
Timo Sirainen <tss@iki.fi>
parents:
3967
diff
changeset
|
526 const char *key, long long diff) |
3793 | 527 { |
528 struct client_dict_transaction_context *ctx = | |
529 (struct client_dict_transaction_context *)_ctx; | |
530 const char *query; | |
531 | |
532 t_push(); | |
3990
e2e6919c6c4d
LF wasn't sent at the end of all commands.
Timo Sirainen <tss@iki.fi>
parents:
3967
diff
changeset
|
533 query = t_strdup_printf("%c%u\t%s\t%lld\n", |
e2e6919c6c4d
LF wasn't sent at the end of all commands.
Timo Sirainen <tss@iki.fi>
parents:
3967
diff
changeset
|
534 DICT_PROTOCOL_CMD_ATOMIC_INC, |
3793 | 535 ctx->id, dict_client_escape(key), diff); |
4368 | 536 (void)client_dict_send_transaction_query(ctx, query); |
3793 | 537 t_pop(); |
538 } | |
539 | |
4517
e661182eab75
Berkeley DB dict support is now enabled only when using --with-db configure option.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4516
diff
changeset
|
540 struct dict dict_driver_client = { |
3793 | 541 MEMBER(name) "proxy", |
542 | |
543 { | |
544 client_dict_init, | |
545 client_dict_deinit, | |
546 client_dict_lookup, | |
547 client_dict_iterate_init, | |
548 client_dict_iterate, | |
549 client_dict_iterate_deinit, | |
550 client_dict_transaction_init, | |
551 client_dict_transaction_commit, | |
552 client_dict_transaction_rollback, | |
553 client_dict_set, | |
4516
aa2f73a4df26
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Timo Sirainen <timo.sirainen@movial.fi>
parents:
4512
diff
changeset
|
554 client_dict_unset, |
3793 | 555 client_dict_atomic_inc |
556 } | |
557 }; |