OSDN Git Service

* Fixed Bug.
[modchxj/mod_chxj.git] / src / chxj_mysql.c
1 /*
2  * Copyright (C) 2005-2009 Atsushi Konno All rights reserved.
3  * Copyright (C) 2005 QSDN,Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifdef USE_MYSQL_COOKIE
18 #include "mod_chxj.h"
19 #include "chxj_cookie.h"
20 #include "chxj_url_encode.h"
21 #include "chxj_apply_convrule.h"
22
23 #include "ap_release.h"
24
25 #include "apu.h"
26 #include "apr_uuid.h"
27 #include "apr_md5.h"
28 #include "apr_base64.h"
29 #include "apr_uri.h"
30
31 #include <unistd.h>
32
33 /* for MySQL */
34 #include <mysql.h>
35 #include <errmsg.h>
36
37
38 #define CHXJ_MYSQL_RECONNECT_WAIT_TIME (5000)
39 #define CHXJ_MYSQL_RECONNECT_COUNT (3)
40
41 typedef struct {
42   MYSQL *handle;
43   char host[255];
44   char username[255];
45   char database[255];
46   time_t last_used;
47   int reconnect;
48 } mysql_connection;
49
50 static mysql_connection connection = {NULL, "", "", "", 0, 0};
51
52
53 static apr_status_t
54 _mysql_cleanup(void *UNUSED(notused))
55 {
56   chxj_close_mysql_handle();
57   return APR_SUCCESS;
58 }
59
60 static apr_status_t
61 _mysql_cleanup_child(void *UNUSED(notused))
62 {
63   return APR_SUCCESS;
64 }
65
66
67 void
68 chxj_close_mysql_handle()
69 {
70   if (connection.handle) {
71     mysql_close(connection.handle);
72     connection.handle = NULL;
73   }
74 }
75
76 int
77 chxj_open_mysql_handle(request_rec *r, mod_chxj_config *m)
78 {
79   static MYSQL mysql_conn;
80   char query[MAX_STRING_LEN];
81
82   if (connection.handle && connection.reconnect == 0) {
83     if ((!m->mysql.host || (strcasecmp(m->mysql.host, "localhost") == 0)) && connection.host[0] == '\0'
84         &&  (m->mysql.username && strcmp(m->mysql.username, connection.username) == 0)) {
85
86       if (m->mysql.database && strcmp(m->mysql.database, connection.database) == 0) {
87         DBG(r, "already connected");
88         DBG(r, "end chxj_open_mysql_handle()");
89         return 1;
90       }
91       else {
92         if (mysql_select_db(connection.handle,m->mysql.database) != 0) {
93           ERR(r, "%s:%d MySQL ERROR: %s", APLOG_MARK, mysql_error(connection.handle));
94           return 0;
95         }
96         else {
97           strcpy (connection.database, m->mysql.database);
98           DBG(r, "already connected. new database:[%s]", m->mysql.database);
99           return 1;
100         }
101       }
102     }
103   }
104
105   chxj_close_mysql_handle();
106   connection.handle = mysql_init(&mysql_conn);
107   if (! connection.handle) {
108     ERR(r, "%s:%d MySQL ERROR: %s", APLOG_MARK, mysql_error(&mysql_conn));
109     return 0;
110   }
111
112   if (!m->mysql.host || strcmp(m->mysql.host,"localhost") == 0) {
113     connection.host[0] = '\0';
114   } else {
115     strcpy(connection.host, m->mysql.host);
116   }
117
118   connection.handle = mysql_real_connect(&mysql_conn,connection.host,m->mysql.username,
119                                   m->mysql.password, NULL, m->mysql.port, m->mysql.socket_path, 0);
120   if (!connection.handle) {
121     ERR(r, "MySQL ERROR: %s. host:[%s] username:[%s] password:[%s] port:[%d] socket_path:[%s]", mysql_error(&mysql_conn), 
122        connection.host, 
123        m->mysql.username,
124        m->mysql.password,
125        m->mysql.port,
126        m->mysql.socket_path);
127     DBG(r, "end chxj_open_mysql_handle()");
128     return 0;
129   }
130
131   apr_pool_cleanup_register(r->pool, (void *)NULL, _mysql_cleanup, _mysql_cleanup_child);
132   if (m->mysql.username) {
133     strcpy(connection.username, m->mysql.username);
134   }
135   else {
136     connection.username[0] = '\0';
137   }
138
139   if (mysql_select_db(connection.handle,m->mysql.database) != 0) {
140     ERR(r, "%s:%d MySQL ERROR: %s", APLOG_MARK, mysql_error(connection.handle));
141     return 0;
142   }
143
144   strcpy (connection.database, m->mysql.database);
145   if (m->mysql.charset) {
146     apr_snprintf(query, sizeof(query)-1, "SET CHARACTER SET %s", m->mysql.charset);
147     if (mysql_query(connection.handle, query) != 0) {
148       ERR(r, "%s:%d MySQL ERROR: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
149       return 0;
150     }
151   }
152
153   DBG(r, "end chxj_open_mysql_handle()");
154   return 1;
155 }
156
157
158 int
159 chxj_mysql_exist_cookie_table(request_rec *r, mod_chxj_config *m)
160 {
161   MYSQL_RES *result;
162   char query[MAX_STRING_LEN];
163   int retry_count = 0;
164   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
165
166   apr_snprintf(query, sizeof(query)-1, "desc %s", m->mysql.tablename);
167   DBG(r, "start chxj_mysql_exist_cookie_table() query:[%s]", query);
168   do { 
169     if (!chxj_open_mysql_handle(r, m)) {
170       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK, query);
171       return 0;
172     }
173     connection.reconnect = 0;
174     if (mysql_query(connection.handle, query) != 0) {
175       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
176         connection.reconnect = 1;
177         retry_count++;
178         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
179           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
180           return 0;
181         }
182         apr_sleep(wait_time);
183         continue;
184       }
185       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
186       return 0;
187     }
188   }
189   while(0);
190
191   result = mysql_store_result(connection.handle);
192   if (result) mysql_free_result(result);
193   
194   DBG(r, "end chxj_mysql_exist_cookie_table() query:[%s]", query);
195
196   return 1;
197 }
198
199
200 int
201 chxj_mysql_exist_cookie_table_expire(request_rec *r, mod_chxj_config *m)
202 {
203   MYSQL_RES *result;
204   char query[MAX_STRING_LEN];
205   int retry_count = 0;
206   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
207
208   apr_snprintf(query, sizeof(query)-1, "desc %s_expire", m->mysql.tablename);
209
210   DBG(r, "start chxj_mysql_exist_cookie_table_expire() query:[%s]", query);
211
212   do { 
213     if (!chxj_open_mysql_handle(r, m)) {
214       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK, query);
215       return 0;
216     }
217     connection.reconnect = 0;
218     if (mysql_query(connection.handle, query) != 0) {
219       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
220         connection.reconnect = 1;
221         retry_count++;
222         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
223           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
224           return 0;
225         }
226         apr_sleep(wait_time);
227         continue;
228       }
229       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
230       return 0;
231     }
232   } while(0);
233
234   result = mysql_store_result(connection.handle);
235   if (result) mysql_free_result(result);
236
237   DBG(r, "end chxj_mysql_exist_cookie_table_expire() query:[%s]", query);
238
239   return 1;
240 }
241
242
243 int
244 chxj_mysql_create_cookie_table(request_rec *r, mod_chxj_config *m)
245 {
246   MYSQL_RES *result;
247   char query[MAX_STRING_LEN];
248   int retry_count = 0;
249   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
250
251   apr_snprintf(query, sizeof(query)-1, "CREATE TABLE %s  (cookie_id VARCHAR(%d) NOT NULL, data TEXT, PRIMARY KEY(cookie_id)) TYPE=InnoDB;",
252     m->mysql.tablename,
253     apr_base64_encode_len(APR_MD5_DIGESTSIZE) * 3);
254   DBG(r, "start chxj_mysql_create_cookie_table() query:[%s]", query);
255   do {
256     if (!chxj_open_mysql_handle(r, m)) {
257       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK, query);
258       return 0;
259     }
260     connection.reconnect = 0;
261     if (mysql_query(connection.handle, query) != 0) {
262       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
263         connection.reconnect = 1;
264         retry_count++;
265         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
266           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
267           return 0;
268         }
269         apr_sleep(wait_time);
270         continue;
271       }
272       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
273       return 0;
274     }
275   }
276   while(0);
277
278   result = mysql_store_result(connection.handle);
279   if (result) mysql_free_result(result);
280   
281   DBG(r, "end chxj_mysql_create_cookie_table() query:[%s]", query);
282
283   return 1;
284 }
285
286 int
287 chxj_mysql_create_cookie_expire_table(request_rec *r, mod_chxj_config *m)
288 {
289   MYSQL_RES *result;
290   char query[MAX_STRING_LEN];
291   int retry_count = 0;
292   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
293
294   apr_snprintf(query, sizeof(query)-1, "CREATE TABLE %s_expire  (cookie_id VARCHAR(%d) NOT NULL, created_at DATETIME, PRIMARY KEY(cookie_id)) TYPE=InnoDB;",
295     m->mysql.tablename,
296     apr_base64_encode_len(APR_MD5_DIGESTSIZE) * 3);
297
298   DBG(r, "start chxj_mysql_create_cookie_expire_table() query:[%s]", query);
299
300   do {
301     if (!chxj_open_mysql_handle(r, m)) {
302       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK, query);
303       return 0;
304     }
305     connection.reconnect = 0;
306     if (mysql_query(connection.handle, query) != 0) {
307       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
308         connection.reconnect = 1;
309         retry_count++;
310         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
311           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
312           return 0;
313         }
314         apr_sleep(wait_time);
315         continue;
316       }
317       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
318       return 0;
319     }
320   }
321   while(0);
322
323   result = mysql_store_result(connection.handle);
324   if (result) mysql_free_result(result);
325   
326   DBG(r, "end chxj_mysql_create_cookie_expire_table() query:[%s]", query);
327
328   return 1;
329 }
330
331
332 char *
333 chxj_mysql_get_cookie_from_cookie_id(request_rec *r, mod_chxj_config *m, const char *cookie_id)
334 {
335   MYSQL_RES *result;
336   char query[MAX_STRING_LEN];
337   char *retval = NULL;
338   apr_size_t clen = strlen(cookie_id);
339   char *sql_safe_cookie_id = apr_palloc(r->pool, clen*2+1);
340   int retry_count = 0;
341   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
342
343   mysql_escape_string(sql_safe_cookie_id,cookie_id,clen);
344
345   apr_snprintf(query, sizeof(query)-1, "SELECT data, length(data) FROM %s WHERE cookie_id = '%s'", m->mysql.tablename, sql_safe_cookie_id);
346   DBG(r, "start chxj_mysql_get_cookie_from_cookie_id() query:[%s]", query);
347   do {
348     if (!chxj_open_mysql_handle(r, m)) {
349       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK, query);
350       return 0;
351     }
352     connection.reconnect = 0;
353     if (mysql_query(connection.handle, query) != 0) {
354       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
355         connection.reconnect = 1;
356         retry_count++;
357         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
358           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
359           return 0;
360         }
361         apr_sleep(wait_time);
362         continue;
363       }
364       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
365       return NULL;
366     }
367   }
368   while(0);
369
370   result = mysql_store_result(connection.handle);
371   if (result && (mysql_num_rows(result) >= 1)) {
372     MYSQL_ROW data = mysql_fetch_row(result);
373     int len;
374     if (! data[0]) {
375       mysql_free_result(result);
376       ERR(r, "%s:%d MySQL cookie_id:[%s] has no valid cookie_id. %s", APLOG_MARK, cookie_id, r->uri);
377       return NULL;
378     }
379     len = atoi(data[1]);
380     retval = (char *) apr_palloc(r->pool, len + 1);
381     memcpy(retval, data[0], len);
382   }
383   if (result) mysql_free_result(result);
384
385   
386   DBG(r, "end chxj_mysql_get_cookie_from_cookie_id() query:[%s]", query);
387
388   return retval;
389 }
390
391
392 char *
393 chxj_mysql_get_cookie_expire_from_cookie_id(request_rec *r, mod_chxj_config *m, const char *cookie_id)
394 {
395   MYSQL_RES *result;
396   char query[MAX_STRING_LEN];
397   apr_size_t clen = strlen(cookie_id);
398   char *retval = NULL;
399   char *sql_safe_cookie_id = apr_palloc(r->pool, clen*2+1);
400   int retry_count = 0;
401   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
402
403   mysql_escape_string(sql_safe_cookie_id,cookie_id,clen);
404
405   apr_snprintf(query, sizeof(query)-1, "SELECT DATE_FORMAT(created_at, '%%Y%%m%%d%%H%%i%%s') FROM %s_expire WHERE cookie_id = '%s'", 
406     m->mysql.tablename, sql_safe_cookie_id);
407
408   DBG(r, "start chxj_mysql_get_cookie_expire_from_cookie_id() query:[%s]", query);
409
410   do {
411     if (!chxj_open_mysql_handle(r, m)) {
412       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK, query);
413       return NULL;
414     }
415     connection.reconnect = 0;
416     if (mysql_query(connection.handle, query) != 0) {
417       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
418         connection.reconnect = 1;
419         retry_count++;
420         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
421           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
422           return 0;
423         }
424         apr_sleep(wait_time);
425         continue;
426       }
427       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
428       return NULL;
429     }
430   }
431   while(0);
432
433   result = mysql_store_result(connection.handle);
434   if (result && (mysql_num_rows(result) >= 1)) {
435     MYSQL_ROW data = mysql_fetch_row(result);
436     if (! data[0]) {
437       mysql_free_result(result);
438       ERR(r, "%s:%d MySQL cookie_id:[%s] has no valid cookie_id. %s", APLOG_MARK, cookie_id, r->uri);
439       return NULL;
440     }
441     retval = (char *) apr_palloc(r->pool, 19 + 1);
442     memset(retval, 0, 19+1);
443     memcpy(retval, data[0], 19);
444   }
445   if (result) mysql_free_result(result);
446   
447   DBG(r, "end chxj_mysql_get_cookie_expire_from_cookie_id() query:[%s] retval:[%s]", query, retval);
448
449   return retval;
450 }
451
452
453 int
454 chxj_mysql_insert_or_update_cookie(request_rec *r, mod_chxj_config *m, const char *cookie_id, const char *data)
455 {
456   MYSQL_RES *result;
457   char query[MAX_STRING_LEN];
458   char *cid = ap_escape_logitem(r->pool, cookie_id);
459   char *cdt = ap_escape_logitem(r->pool, data);
460   int retry_count = 0;
461   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
462
463   DBG(r, "start chxj_mysql_insert_or_update_cookie() data:[%s]", data);
464   do {
465     if (!chxj_open_mysql_handle(r, m)) {
466       ERR(r, "%s:%d failed chxj_open_mysql_handle()", APLOG_MARK);
467       return 0;
468     }
469     connection.reconnect = 0;
470     apr_snprintf(query, sizeof(query)-1, "BEGIN;");
471     DBG(r, "query:[%s]", query);
472     if (mysql_query(connection.handle, query) != 0) {
473       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
474         connection.reconnect = 1;
475         retry_count++;
476         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
477           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
478           return 0;
479         }
480         apr_sleep(wait_time);
481         continue;
482       }
483       ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
484       return 0;
485     }
486   }
487   while(0);
488
489   apr_snprintf(query, sizeof(query)-1, "INSERT INTO %s (cookie_id, data) VALUES ('%s','%s');", m->mysql.tablename, cid, cdt);
490   DBG(r, "query:[%s]", query);
491   if (mysql_query(connection.handle, query) != 0) {
492     WRN(r, "MySQL WARN: %s: %s", mysql_error(connection.handle), r->uri);
493     if (!chxj_mysql_get_cookie_from_cookie_id(r, m, cookie_id)) {
494       ERR(r, "%s:%d failed chxj_mysql_get_cookie_from_cookie_id() cookie_id:[%s]", APLOG_MARK, cookie_id);
495       return 0;
496     }
497     apr_snprintf(query, sizeof(query)-1, "UPDATE %s set data = '%s' WHERE cookie_id = '%s';", m->mysql.tablename, cdt, cid);
498     DBG(r, "query:[%s]", query);
499     if (mysql_query(connection.handle, query) != 0) {
500       ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
501       chxj_mysql_rollback(r, m);
502       return 0;
503     }
504   }
505
506   apr_snprintf(query, sizeof(query)-1, "COMMIT;");
507   DBG(r, "query:[%s]", query);
508   if (mysql_query(connection.handle, query) != 0) {
509     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
510     chxj_mysql_rollback(r, m);
511     return 0;
512   }
513
514   result = mysql_store_result(connection.handle);
515   if (result) mysql_free_result(result);
516   
517   DBG(r, "end chxj_mysql_get_cookie_from_cookie_id()");
518
519   return 1;
520 }
521
522
523 int
524 chxj_mysql_insert_or_update_cookie_expire(request_rec *r, mod_chxj_config *m, const char *cookie_id)
525 {
526   MYSQL_RES *result;
527   char query[MAX_STRING_LEN];
528   char *cid = ap_escape_logitem(r->pool, cookie_id);
529   int retry_count = 0;
530   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
531
532   DBG(r, "start chxj_mysql_insert_or_update_cookie_expire()");
533
534   do {
535     if (!chxj_open_mysql_handle(r, m)) {
536       ERR(r, "%s:%d failed chxj_open_mysql_handle()", APLOG_MARK);
537       return 0;
538     }
539     connection.reconnect = 0; 
540     apr_snprintf(query, sizeof(query)-1, "BEGIN;");
541     DBG(r, "query:[%s]", query);
542     if (mysql_query(connection.handle, query) != 0) {
543       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
544         connection.reconnect = 1;
545         retry_count++;
546         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
547           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
548           return 0;
549         }
550         apr_sleep(wait_time);
551         continue;
552       }
553       ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK,mysql_error(connection.handle), r->uri);
554       return 0;
555     }
556   }
557   while(0);
558
559   apr_snprintf(query, sizeof(query)-1, "INSERT INTO %s_expire (cookie_id, created_at) VALUES ('%s',localtime);", m->mysql.tablename, cid);
560   DBG(r, "query:[%s]", query);
561   if (mysql_query(connection.handle, query) != 0) {
562     WRN(r, "MySQL WARN: %s: %s", mysql_error(connection.handle), r->uri);
563     if (!chxj_mysql_get_cookie_from_cookie_id(r, m, cookie_id)) {
564       ERR(r, "%s:%d failed chxj_mysql_get_cookie_from_cookie_id() cookie_id:[%s]", APLOG_MARK, cookie_id);
565       return 0;
566     }
567     apr_snprintf(query, sizeof(query)-1, "UPDATE %s_expire set created_at = localtime WHERE cookie_id = '%s';", m->mysql.tablename, cid);
568     DBG(r, "query:[%s]", query);
569     if (mysql_query(connection.handle, query) != 0) {
570       ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
571       chxj_mysql_rollback(r, m);
572       return 0;
573     }
574   }
575
576   apr_snprintf(query, sizeof(query)-1, "COMMIT;");
577   DBG(r, "query:[%s]", query);
578   if (mysql_query(connection.handle, query) != 0) {
579     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
580     chxj_mysql_rollback(r, m);
581     return 0;
582   }
583
584   result = mysql_store_result(connection.handle);
585   if (result) mysql_free_result(result);
586   
587   DBG(r, "end chxj_mysql_insert_or_update_cookie_expire()");
588
589   return 1;
590 }
591
592
593 int
594 chxj_mysql_rollback(request_rec *r, mod_chxj_config *m)
595 {
596   char query[MAX_STRING_LEN];
597
598   DBG(r, "start chxj_mysql_rollback()");
599
600   apr_snprintf(query, sizeof(query)-1, "ROLLBACK;");
601
602   if (!chxj_open_mysql_handle(r, m)) {
603     DBG(r, "end chxj_mysql_rollback()");
604     return 1; /* TRUE */
605   }
606   if (mysql_query(connection.handle, query) != 0) {
607     ERR(r, "%s:%d MySQL ERROR: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
608     return 0; /* FALSE */
609   }
610   DBG(r, "end chxj_mysql_rollback()");
611   return 1;
612 }
613
614 char *
615 chxj_mysql_load_cookie(request_rec *r, mod_chxj_config *m, const char *cookie_id)
616 {
617   MYSQL_RES *result;
618   char query[MAX_STRING_LEN];
619   apr_size_t clen = strlen(cookie_id);
620   char *retval = NULL;
621   char *sql_safe_cookie_id = apr_palloc(r->pool, clen*2+1);
622   int retry_count = 0;
623   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
624   
625   mysql_escape_string(sql_safe_cookie_id,cookie_id,clen);
626
627   apr_snprintf(query, sizeof(query)-1, "SELECT data, length(data) FROM %s WHERE cookie_id = '%s';", m->mysql.tablename, sql_safe_cookie_id);
628
629   DBG(r, "start chxj_mysql_load_cookie() query:[%s]", query);
630
631   do {
632     if (!chxj_open_mysql_handle(r, m)) {
633       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK, query);
634       return NULL;
635     }
636     connection.reconnect = 0;
637     if (mysql_query(connection.handle, query) != 0) {
638       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
639         connection.reconnect = 1;
640         retry_count++;
641         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
642           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
643           return NULL;
644         }
645         apr_sleep(wait_time);
646         continue;
647       }
648       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
649       return NULL;
650     }
651   }
652   while(0);
653
654   result = mysql_store_result(connection.handle);
655   if (result && (mysql_num_rows(result) >= 1)) {
656     MYSQL_ROW data = mysql_fetch_row(result);
657     int len;
658     if (! data[0]) {
659       ERR(r, "%s:%d MySQL cookie_id:[%s] has no valid cookie_id. %s", APLOG_MARK, cookie_id, r->uri);
660       mysql_free_result(result);
661       return NULL;
662     }
663     len = atoi(data[1]);
664     retval = (char *) apr_palloc(r->pool, len + 1);
665     memset(retval, 0, len + 1);
666     memcpy(retval, data[0], len);
667   }
668   if (result) mysql_free_result(result);
669   
670   DBG(r, "end chxj_load_mysql_cookie() query:[%s]", query);
671
672   return retval;
673 }
674
675
676 char *
677 chxj_mysql_load_cookie_expire(request_rec *r, mod_chxj_config *m, const char *cookie_id)
678 {
679   MYSQL_RES *result;
680   char query[MAX_STRING_LEN];
681   char *retval = NULL;
682   apr_size_t clen = strlen(cookie_id);
683   char *sql_safe_cookie_id = apr_palloc(r->pool, clen*2+1);
684   int retry_count = 0;
685   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
686
687   mysql_escape_string(sql_safe_cookie_id,cookie_id,clen);
688
689   apr_snprintf(query, 
690                sizeof(query)-1, 
691                "SELECT DATE_FORMAT(created_at, '%%Y%%m%%d%%H%%i%%s') FROM %s_expire WHERE cookie_id = '%s';", 
692                m->mysql.tablename, 
693                sql_safe_cookie_id);
694
695   DBG(r, "start chxj_mysql_load_cookie_expire() query:[%s]", query);
696
697   do {
698     if (!chxj_open_mysql_handle(r, m)) {
699       ERR(r, "%s:%d failed chxj_open_mysql_handle() query:[%s]", APLOG_MARK,query);
700       return NULL;
701     }
702     connection.reconnect = 0;
703     if (mysql_query(connection.handle, query) != 0) {
704       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
705         connection.reconnect = 1;
706         retry_count++;
707         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
708           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK,mysql_error(connection.handle), r->uri);
709           return 0;
710         }
711         apr_sleep(wait_time);
712         continue;
713       }
714       WRN(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
715       return NULL;
716     }
717   }
718   while(0);
719
720   result = mysql_store_result(connection.handle);
721   if (result && (mysql_num_rows(result) >= 1)) {
722     MYSQL_ROW data = mysql_fetch_row(result);
723     if (! data[0]) {
724       ERR(r, "%s:%d MySQL cookie_id:[%s] has no valid cookie_id. %s", APLOG_MARK,cookie_id, r->uri);
725       mysql_free_result(result);
726       return NULL;
727     }
728     retval = (char *) apr_palloc(r->pool, 14 + 1);
729     memcpy(retval, data[0], 14);
730   }
731   if (result) mysql_free_result(result);
732   
733   DBG(r, "end chxj_mysql_load_cookie_expire() query:[%s]", query);
734
735   return retval;
736 }
737
738
739 int
740 chxj_mysql_delete_cookie(request_rec *r, mod_chxj_config *m, const char *cookie_id)
741 {
742   MYSQL_RES *result;
743   char query[MAX_STRING_LEN];
744   char *cid = ap_escape_logitem(r->pool, cookie_id);
745   int retry_count = 0;
746   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
747
748   DBG(r, "start chxj_mysql_delete_cookie() cookie_id:[%s]", cookie_id);
749
750   do {
751     if (!chxj_open_mysql_handle(r, m)) {
752       ERR(r, "%s:%d failed chxj_open_mysql_handle()", APLOG_MARK);
753       return 0;
754     }
755     connection.reconnect = 0;
756     apr_snprintf(query, sizeof(query)-1, "BEGIN;");
757     DBG(r, "query:[%s]", query);
758     if (mysql_query(connection.handle, query) != 0) {
759       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
760         connection.reconnect = 1;
761         retry_count++;
762         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
763           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK,mysql_error(connection.handle), r->uri);
764           return 0;
765         }
766         apr_sleep(wait_time);
767         continue;
768       }
769       ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
770       return 0;
771     }
772   }
773   while(0);
774
775   if (!chxj_mysql_get_cookie_from_cookie_id(r, m, cookie_id)) {
776     ERR(r, "%s:%d failed chxj_mysql_get_cookie_from_cookie_id() cookie_id:[%s]", APLOG_MARK,cookie_id);
777     return 0;
778   }
779   apr_snprintf(query, sizeof(query)-1, "DELETE FROM %s WHERE cookie_id = '%s';", m->mysql.tablename, cid);
780   DBG(r, "query:[%s]", query);
781   if (mysql_query(connection.handle, query) != 0) {
782     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
783     chxj_mysql_rollback(r, m);
784     return 0;
785   }
786
787   apr_snprintf(query, sizeof(query)-1, "COMMIT;");
788   DBG(r, "query:[%s]", query);
789   if (mysql_query(connection.handle, query) != 0) {
790     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
791     chxj_mysql_rollback(r, m);
792     return 0;
793   }
794
795   result = mysql_store_result(connection.handle);
796   if (result) mysql_free_result(result);
797   
798   DBG(r, "end chxj_mysql_delete_cookie()");
799
800   return 1;
801 }
802
803
804 int
805 chxj_mysql_delete_cookie_expire(request_rec *r, mod_chxj_config *m, const char *cookie_id)
806 {
807   MYSQL_RES *result;
808   char query[MAX_STRING_LEN];
809   char *cid = ap_escape_logitem(r->pool, cookie_id);
810   int retry_count = 0;
811   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
812
813   DBG(r, "start chxj_mysql_delete_cookie_expire() cookie_id:[%s]", cookie_id);
814
815   do {
816     if (!chxj_open_mysql_handle(r, m)) {
817       ERR(r, "%s:%d failed chxj_open_mysql_handle()", APLOG_MARK);
818       return 0;
819     }
820     connection.reconnect = 0; 
821     apr_snprintf(query, sizeof(query)-1, "BEGIN;");
822     DBG(r, "query:[%s]", query);
823     if (mysql_query(connection.handle, query) != 0) {
824       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
825         connection.reconnect = 1;
826         retry_count++;
827         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
828           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK,mysql_error(connection.handle), r->uri);
829           return 0;
830         }
831         apr_sleep(wait_time);
832         continue;
833       }
834       ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK,mysql_error(connection.handle), r->uri);
835       return 0;
836     }
837   }
838   while(0);
839
840   if (!chxj_mysql_get_cookie_expire_from_cookie_id(r, m, cookie_id)) {
841     ERR(r, "%s:%d failed chxj_mysql_get_cookie_expire_from_cookie_id() cookie_id:[%s]", APLOG_MARK,cookie_id);
842     return 0;
843   }
844   apr_snprintf(query, sizeof(query)-1, "DELETE FROM %s_expire WHERE cookie_id = '%s';", m->mysql.tablename, cid);
845   DBG(r, "query:[%s]", query);
846   if (mysql_query(connection.handle, query) != 0) {
847     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK,mysql_error(connection.handle), r->uri);
848     chxj_mysql_rollback(r, m);
849     return 0;
850   }
851
852   apr_snprintf(query, sizeof(query)-1, "COMMIT;");
853   DBG(r, "query:[%s]", query);
854   if (mysql_query(connection.handle, query) != 0) {
855     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
856     chxj_mysql_rollback(r, m);
857     return 0;
858   }
859
860   result = mysql_store_result(connection.handle);
861   if (result) mysql_free_result(result);
862   
863   DBG(r, "end chxj_mysql_delete_cookie_expire() cookie_id:[%s]", cookie_id);
864
865   return 1;
866 }
867
868 char *
869 chxj_mysql_get_timeout_localtime(request_rec *r, mod_chxj_config *m)
870 {
871   MYSQL_RES *result;
872   char query[MAX_STRING_LEN];
873   char *retval = NULL;
874   int retry_count = 0;
875   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
876
877   DBG(r, "start chxj_mysql_get_timeout_localtime()");
878   do {
879     if (!chxj_open_mysql_handle(r, m)) {
880       ERR(r, "%s:%d failed chxj_open_mysql_handle()", APLOG_MARK);
881       return 0;
882     }
883     connection.reconnect = 0;
884     apr_snprintf(query, sizeof(query)-1, "SELECT DATE_SUB(localtime, interval %ld second);",
885       (m->cookie_timeout == 0) ? DEFAULT_COOKIE_TIMEOUT : m->cookie_timeout);
886     DBG(r, "query:[%s]", query);
887     if (mysql_query(connection.handle, query) != 0) {
888       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
889         connection.reconnect = 1;
890         retry_count++;
891         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
892           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK, mysql_error(connection.handle), r->uri);
893           return 0;
894         }
895         apr_sleep(wait_time);
896         continue;
897       }
898       ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
899       return NULL;
900     }
901   }
902   while(0);
903   result = mysql_store_result(connection.handle);
904   if (result && (mysql_num_rows(result) >= 1)) {
905     MYSQL_ROW data = mysql_fetch_row(result);
906     if (! data[0]) {
907       ERR(r, "%s:%d MySQL ERROR: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
908       mysql_free_result(result);
909       return NULL;
910     }
911     retval = (char *) apr_palloc(r->pool, 19 + 1);
912     memset(retval, 0, 19+1);
913     memcpy(retval, data[0], 19);
914   }
915   if (result) mysql_free_result(result);
916    
917   DBG(r, "end chxj_mysql_get_timeout_localtime()");
918
919   return retval;
920 }
921
922 int
923 chxj_mysql_delete_expired_cookie(request_rec *r, mod_chxj_config *m)
924 {
925   MYSQL_RES *result;
926   char query[MAX_STRING_LEN];
927   char *timeout;
928   int retry_count = 0;
929   apr_interval_time_t wait_time = CHXJ_MYSQL_RECONNECT_WAIT_TIME;
930
931   DBG(r, "start chxj_mysql_delete_expired_cookie()");
932
933   do {
934     if (!chxj_open_mysql_handle(r, m)) {
935       ERR(r, "%s:%d failed chxj_open_mysql_handle()", APLOG_MARK);
936       return 0;
937     }
938     connection.reconnect = 0;
939     apr_snprintf(query, sizeof(query)-1, "BEGIN;");
940     DBG(r, "query:[%s]", query);
941     if (mysql_query(connection.handle, query) != 0) {
942       if (mysql_errno(connection.handle) == CR_SERVER_GONE_ERROR) {
943         connection.reconnect = 1;
944         retry_count++;
945         if (retry_count >= CHXJ_MYSQL_RECONNECT_COUNT) {
946           ERR(r, "%s:%d MySQL ERROR: %s: %s(retry over)", APLOG_MARK,mysql_error(connection.handle), r->uri);
947           return 0;
948         }
949         apr_sleep(wait_time);
950         continue;
951       }
952       ERR(r, "%s:%d MySQL ERROR: %s: %s", APLOG_MARK,mysql_error(connection.handle), r->uri);
953       return 0;
954     }
955   }
956   while (0);
957
958   timeout = chxj_mysql_get_timeout_localtime(r, m);
959   if (! timeout) {
960     ERR(r, "%s:%d MySQL ERROR: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
961     return 0;
962   }
963
964   apr_snprintf(query, sizeof(query)-1, "SELECT * FROM %s_expire WHERE created_at <= '%s'", m->mysql.tablename, timeout);
965   DBG(r, "query:[%s]", query);
966   if (mysql_query(connection.handle, query) != 0) {
967     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK,mysql_error(connection.handle), r->uri);
968     chxj_mysql_rollback(r, m);
969     return 0;
970   }
971   result = mysql_store_result(connection.handle);
972   if (result) mysql_free_result(result);
973   result = NULL;
974
975   /* delete from chxj_cookie */
976   apr_snprintf(query, sizeof(query)-1, "DELETE %s FROM %s, %s_expire WHERE %s_expire.created_at <= '%s' AND %s.cookie_id = %s_expire.cookie_id;", 
977      m->mysql.tablename, 
978      m->mysql.tablename,
979      m->mysql.tablename,
980      m->mysql.tablename,
981      timeout,
982      m->mysql.tablename,
983      m->mysql.tablename);
984   DBG(r, "query:[%s]", query);
985   if (mysql_query(connection.handle, query) != 0) {
986     ERR(r, "%s:%d MySQL ERROR: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
987     chxj_mysql_rollback(r, m);
988     return 0;
989   }
990   result = mysql_store_result(connection.handle);
991   if (result) mysql_free_result(result);
992   result = NULL;
993
994   /* delete from chxj_cookie_expire */
995   apr_snprintf(query, sizeof(query)-1, "DELETE %s_expire FROM %s_expire WHERE %s_expire.created_at <= '%s';", 
996      m->mysql.tablename, 
997      m->mysql.tablename,
998      m->mysql.tablename,
999      timeout);
1000   DBG(r, "query:[%s]", query);
1001   if (mysql_query(connection.handle, query) != 0) {
1002     ERR(r, "%s:%d MySQL ERROR: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
1003     chxj_mysql_rollback(r, m);
1004     return 0;
1005   }
1006   result = mysql_store_result(connection.handle);
1007   if (result) mysql_free_result(result);
1008   result = NULL;
1009
1010   apr_snprintf(query, sizeof(query)-1, "COMMIT;");
1011   DBG(r, "query:[%s]", query);
1012   if (mysql_query(connection.handle, query) != 0) {
1013     ERR(r, "%s:%d MySQL WARN: %s: %s", APLOG_MARK, mysql_error(connection.handle), r->uri);
1014     chxj_mysql_rollback(r, m);
1015     return 0;
1016   }
1017
1018   result = mysql_store_result(connection.handle);
1019   if (result) mysql_free_result(result);
1020
1021   DBG(r, "end chxj_mysql_delete_expired_cookie()");
1022   return 1;
1023 }
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 int
1036 chxj_save_cookie_mysql(request_rec *r, mod_chxj_config *m, const char *cookie_id, const char *store_string)
1037 {
1038   DBG(r, "start chxj_save_cookie_mysql()");
1039   if (! chxj_open_mysql_handle(r, m)) {
1040     ERR(r, "Cannot open mysql connection");
1041     DBG(r, "end chxj_save_cookie_mysql()");
1042     return CHXJ_FALSE;
1043   }
1044
1045   if (!chxj_mysql_exist_cookie_table(r, m)) {
1046     DBG(r, "not found cookie table:[%s]", m->mysql.tablename);
1047     if (!chxj_mysql_create_cookie_table(r, m)) {
1048       ERR(r, "cannot create cookie table:[%s]", m->mysql.tablename);
1049       DBG(r, "end chxj_save_cookie_mysql()");
1050       return CHXJ_FALSE;
1051     }
1052   }
1053   if (! chxj_mysql_insert_or_update_cookie(r, m, cookie_id, store_string)) {
1054     ERR(r, "cannot store to cookie table:[%s]", m->mysql.tablename);
1055     DBG(r, "end chxj_save_cookie_mysql()");
1056     return CHXJ_FALSE;
1057   }
1058
1059   /* *NEED NOT* close database. */
1060   DBG(r, "end chxj_save_cookie_mysql()");
1061   return CHXJ_TRUE;
1062 }
1063
1064 int
1065 chxj_update_cookie_mysql(request_rec *r, mod_chxj_config *m, const char *cookie_id, const char *store_string)
1066 {
1067   DBG(r, "start chxj_update_cookie_mysql() cookie_id:[%s]", cookie_id);
1068   if (! chxj_open_mysql_handle(r, m)) {
1069     ERR(r, "Cannot open mysql connection");
1070     DBG(r, "end chxj_update_cookie_mysql() cookie_id:[%s]", cookie_id);
1071     return CHXJ_FALSE;
1072   }
1073
1074   if (!chxj_mysql_exist_cookie_table(r, m)) {
1075     DBG(r, "not found cookie table:[%s]", m->mysql.tablename);
1076     if (!chxj_mysql_create_cookie_table(r, m)) {
1077       ERR(r, "cannot create cookie table:[%s]", m->mysql.tablename);
1078       DBG(r, "end chxj_update_cookie_mysql() cookie_id:[%s]", cookie_id);
1079       return CHXJ_FALSE;
1080     }
1081   }
1082   if (! chxj_mysql_insert_or_update_cookie(r, m, cookie_id, store_string)) {
1083     ERR(r, "cannot create cookie table:[%s]", m->mysql.tablename);
1084     DBG(r, "end chxj_update_cookie_mysql() cookie_id:[%s]", cookie_id);
1085     return CHXJ_FALSE;
1086   }
1087
1088   /* *NEED NOT* close database. */
1089   /* chxj_close_mysql_handle(); */
1090   DBG(r, "end chxj_update_cookie_mysql() cookie_id:[%s]", cookie_id);
1091   return CHXJ_TRUE;
1092 }
1093
1094
1095 char *
1096 chxj_load_cookie_mysql(request_rec *r, mod_chxj_config *m, const char *cookie_id)
1097 {
1098   char *load_string;
1099
1100   DBG(r, "start chxj_load_cookie_mysql() cookie_id:[%s]", cookie_id);
1101   if (! chxj_open_mysql_handle(r, m)) {
1102     ERR(r, "Cannot open mysql connection");
1103     DBG(r, "end   chxj_load_cookie_mysql() cookie_id:[%s]", cookie_id);
1104     return NULL;
1105   }
1106
1107   if (!chxj_mysql_exist_cookie_table(r, m)) {
1108     DBG(r, "not found cookie table:[%s]", m->mysql.tablename);
1109     if (!chxj_mysql_create_cookie_table(r, m)) {
1110       ERR(r, "cannot create cookie table:[%s]", m->mysql.tablename);
1111       DBG(r, "end   chxj_load_cookie_mysql() cookie_id:[%s]", cookie_id);
1112       return NULL;
1113     }
1114   }
1115   if (!(load_string = chxj_mysql_load_cookie(r, m, cookie_id))) {
1116     ERR(r, "%s:%d not found cookie. cookie_id:[%s]", APLOG_MARK, cookie_id);
1117     DBG(r, "end   chxj_load_cookie_mysql() cookie_id:[%s]", cookie_id);
1118     return NULL;
1119   }
1120
1121   /* *NEED NOT* close database. */
1122   /* chxj_close_mysql_handle(); */
1123   DBG(r, "end   chxj_load_cookie_mysql() cookie_id:[%s]", cookie_id);
1124   return load_string;
1125 }
1126
1127
1128 int
1129 chxj_delete_cookie_mysql(request_rec *r, mod_chxj_config *m, const char *cookie_id)
1130 {
1131   DBG(r, "start chxj_delete_cookie_mysql() cookie_id=[%s]", cookie_id);
1132   if (! chxj_open_mysql_handle(r, m)) {
1133     ERR(r, "%s:%d Cannot open mysql connection cookie_id=[%s]", APLOG_MARK, cookie_id);
1134     return CHXJ_FALSE;
1135   }
1136   if (!chxj_mysql_exist_cookie_table(r, m)) {
1137     DBG(r, "not found cookie table:[%s]", m->mysql.tablename);
1138     if (!chxj_mysql_create_cookie_table(r, m)) {
1139       ERR(r, "%s:%d cannot create cookie table:[%s]", APLOG_MARK, m->mysql.tablename);
1140       return CHXJ_FALSE;
1141     }
1142   }
1143   else {
1144     if (!chxj_mysql_delete_cookie(r, m, cookie_id)) {
1145       ERR(r, "%s:%d failed: chxj_mysql_delete_cookie() cookie_id:[%s]", APLOG_MARK, cookie_id);
1146       return CHXJ_FALSE;
1147     }
1148   }
1149   DBG(r, "end chxj_delete_cookie_mysql() cookie_id=[%s]", cookie_id);
1150   return CHXJ_TRUE;
1151 }
1152
1153
1154 int
1155 chxj_save_cookie_expire_mysql(request_rec *r, mod_chxj_config *m, const char *cookie_id)
1156 {
1157   DBG(r, "start chxj_save_cookie_expire_mysql() cookie_id:[%s]", cookie_id);
1158   if (! chxj_open_mysql_handle(r, m)) {
1159     ERR(r, "%s:%d Cannot open mysql connection cookie_id=[%s]",APLOG_MARK, cookie_id);
1160     return CHXJ_FALSE;
1161   }
1162
1163   if (!chxj_mysql_exist_cookie_table_expire(r, m)) {
1164     DBG(r, "not found cookie table:[%s_expire]", m->mysql.tablename);
1165     if (!chxj_mysql_create_cookie_expire_table(r, m)) {
1166       ERR(r, "%s:%d cannot create cookie table:[%s_expire] cookie_id:[%s]", APLOG_MARK, m->mysql.tablename, cookie_id);
1167       return CHXJ_FALSE;
1168     }
1169   }
1170   if (! chxj_mysql_insert_or_update_cookie_expire(r, m, cookie_id)) {
1171     ERR(r, "%s:%d cannot create cookie table:[%s_expire] cookie_id:[%s]", APLOG_MARK, m->mysql.tablename, cookie_id);
1172     return CHXJ_FALSE;
1173   }
1174
1175   /* *NEED NOT* close database. */
1176   /* chxj_close_mysql_handle(); */
1177
1178   DBG(r, "end   chxj_save_cookie_expire_mysql() cookie_id:[%s]", cookie_id);
1179   return CHXJ_TRUE;
1180 }
1181
1182
1183 int
1184 chxj_delete_cookie_expire_mysql(request_rec *r, mod_chxj_config *m, const char *cookie_id)
1185 {
1186   DBG(r, "start chxj_delete_cookie_expire_mysql() cookie_id:[%s]", cookie_id);
1187   if (! chxj_open_mysql_handle(r, m)) {
1188     ERR(r, "%s:%d Cannot open mysql connection", APLOG_MARK);
1189     return CHXJ_FALSE;
1190   }
1191
1192   if (!chxj_mysql_exist_cookie_table_expire(r, m)) {
1193     DBG(r, "not found cookie table:[%s_expire]", m->mysql.tablename);
1194     if (!chxj_mysql_create_cookie_expire_table(r, m)) {
1195       ERR(r, "%s:%d cannot create cookie table:[%s_expire] cookie_id:[%s]", APLOG_MARK, m->mysql.tablename, cookie_id);
1196       return CHXJ_FALSE;
1197     }
1198   } else {
1199     if (!chxj_mysql_delete_cookie_expire(r, m, cookie_id)) {
1200       ERR(r, "%s:%d failed: chxj_mysql_delete_cookie() cookie_id:[%s]", APLOG_MARK, cookie_id);
1201       return CHXJ_FALSE;
1202     }
1203   }
1204   DBG(r, "end   chxj_delete_cookie_expire_mysql() cookie_id:[%s]", cookie_id);
1205   return CHXJ_TRUE;
1206 }
1207
1208
1209 int
1210 chxj_cookie_expire_gc_mysql(request_rec *r, mod_chxj_config *m)
1211 {
1212   DBG(r, "start chxj_cookie_expire_gc_mysql()");
1213   if (! chxj_open_mysql_handle(r, m)) {
1214     ERR(r, "Cannot open mysql connection");
1215     DBG(r, "end chxj_cookie_expire_gc_mysql()");
1216     return CHXJ_FALSE;
1217   }
1218   if (!chxj_mysql_exist_cookie_table_expire(r, m)) {
1219     DBG(r, "not found cookie table:[%s_expire]", m->mysql.tablename);
1220     if (!chxj_mysql_create_cookie_expire_table(r, m)) {
1221       ERR(r, "%s:%d cannot create cookie table:[%s_expire]", APLOG_MARK, m->mysql.tablename);
1222       return CHXJ_FALSE;
1223     }
1224   } else {
1225     if (!chxj_mysql_delete_expired_cookie(r, m)) {
1226       ERR(r, "%s:%d failed: chxj_mysql_delete_expired_cookie()", APLOG_MARK);
1227       return CHXJ_FALSE;
1228     }
1229   }
1230   DBG(r, "end   chxj_cookie_expire_gc_mysql()");
1231   return CHXJ_TRUE;
1232 }
1233
1234
1235 int
1236 chxj_cookie_lock_mysql(request_rec *r, mod_chxj_config *m)
1237 {
1238   MYSQL_RES *result;
1239   char query[MAX_STRING_LEN];
1240   DBG(r, "start chxj_cookie_lock_mysql()");
1241   if (! chxj_open_mysql_handle(r, m)) {
1242     ERR(r, "Cannot open mysql connection");
1243     DBG(r, "end   chxj_save_cookie_expire_mysql()");
1244     return CHXJ_FALSE;
1245   }
1246   if (!chxj_mysql_exist_cookie_table_expire(r, m)) {
1247     DBG(r, "not found cookie table:[%s_expire]", m->mysql.tablename);
1248     if (!chxj_mysql_create_cookie_expire_table(r, m)) {
1249       ERR(r, "cannot create cookie table:[%s_expire]", m->mysql.tablename);
1250       DBG(r, "end chxj_cookie_expire_gc_mysql()");
1251       return CHXJ_FALSE;
1252     }
1253   }
1254   apr_snprintf(query, sizeof(query)-1, "LOCK TABLES %s WRITE", m->mysql.tablename);
1255   DBG(r, "query:[%s]", query);
1256   if (mysql_query(connection.handle, query) != 0) {
1257     chxj_mysql_rollback(r, m);
1258     ERR(r, "MySQL WARN: %s: %s", mysql_error(connection.handle), r->uri);
1259     return CHXJ_FALSE;
1260   }
1261
1262   result = mysql_store_result(connection.handle);
1263   if (result) mysql_free_result(result);
1264   
1265   DBG(r, "end chxj_cookie_lock_mysql()");
1266   return CHXJ_TRUE;
1267 }
1268
1269
1270 int
1271 chxj_cookie_unlock_mysql(request_rec *r, mod_chxj_config *UNUSED(m))
1272 {
1273   char query[MAX_STRING_LEN];
1274   if (r) DBG(r, "start chxj_cookie_unlock_mysql()");
1275   apr_snprintf(query, sizeof(query)-1, "UNLOCK TABLES");
1276   if (mysql_query(connection.handle, query) != 0) {
1277      if (r) {
1278        ERR(r, "MySQL WARN: %s: %s", mysql_error(connection.handle), r->uri);
1279        DBG(r, "end chxj_cookie_unlock_mysql()");
1280      }
1281     return CHXJ_FALSE;
1282   }
1283   if (r) DBG(r, "end chxj_cookie_unlock_mysql()");
1284   return CHXJ_TRUE;
1285 }
1286 #endif
1287 /*
1288  * vim:ts=2 et
1289  */