📄 storage_mysql.c
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002-2003 Jeremie Miller, Thomas Muldowney, * Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA *//** @file sm/storage_mysql.c * @brief mysql storage module * @author Robert Norris * $Date: 2004/11/13 16:08:33 $ * $Revision: 1.13.2.6 $ */#include "sm.h"#ifdef STORAGE_MYSQL#include <mysql.h>/** internal structure, holds our data */typedef struct drvdata_st { MYSQL *conn; char *prefix; xht filters; int txn;} *drvdata_t;#define FALLBACK_BLOCKSIZE (4096)/** internal: do and return the math and ensure it gets realloc'd */static size_t _st_mysql_realloc(void **oblocks, size_t len) { void *nblocks; size_t nlen; static size_t block_size = 0; if (block_size == 0) {#ifdef HAVE_GETPAGESIZE block_size = getpagesize();#elif defined(_SC_PAGESIZE) block_size = sysconf(_SC_PAGESIZE);#elif defined(_SC_PAGE_SIZE) block_size = sysconf(_SC_PAGE_SIZE); #else block_size = FALLBACK_BLOCKSIZE;#endif } /* round up to standard block sizes */ nlen = (((len-1)/block_size)+1)*block_size; /* keep trying till we get it */ while((nblocks = realloc(*oblocks, nlen)) == NULL) sleep(1); *oblocks = nblocks; return nlen;}/** this is the safety check used to make sure there's always enough mem */#define MYSQL_SAFE(blocks, size, len) if((size) >= len) len = _st_mysql_realloc((void**)&(blocks),(size + 1));static void _st_mysql_convert_filter_recursive(st_driver_t drv, st_filter_t f, char **buf, int *buflen, int *nbuf) { drvdata_t data = (drvdata_t) drv->private; st_filter_t scan; char *cval; int vlen; switch(f->type) { case st_filter_type_PAIR: /* do sql escape processing of f->val */ cval = (char *) malloc(sizeof(char) * ((strlen((char *) f->val) * 2) + 1)); vlen = mysql_real_escape_string(data->conn, cval, (char *) f->val, strlen((char *) f->val)); MYSQL_SAFE((*buf), *buflen + 12 + vlen - strlen(f->val), *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), "( `%s` = \'%s\' ) ", f->key, cval); free(cval); break; case st_filter_type_AND: MYSQL_SAFE((*buf), *buflen + 2, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), "( "); for(scan = f->sub; scan != NULL; scan = scan->next) { _st_mysql_convert_filter_recursive(drv, scan, buf, buflen, nbuf); if(scan->next != NULL) { MYSQL_SAFE((*buf), *buflen + 4, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), "AND "); } } MYSQL_SAFE((*buf), *buflen + 2, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), ") "); return; case st_filter_type_OR: MYSQL_SAFE((*buf), *buflen + 2, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), "( "); for(scan = f->sub; scan != NULL; scan = scan->next) { _st_mysql_convert_filter_recursive(drv, scan, buf, buflen, nbuf); if(scan->next != NULL) { MYSQL_SAFE((*buf), *buflen + 3, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), "OR "); } } MYSQL_SAFE((*buf), *buflen + 2, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), ") "); return; case st_filter_type_NOT: MYSQL_SAFE((*buf), *buflen + 6, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), "( NOT "); _st_mysql_convert_filter_recursive(drv, f->sub, buf, buflen, nbuf); MYSQL_SAFE((*buf), *buflen + 2, *buflen); *nbuf += sprintf(&((*buf)[*nbuf]), ") "); return; }}static char *_st_mysql_convert_filter(st_driver_t drv, const char *owner, const char *filter) { drvdata_t data = (drvdata_t) drv->private; char *buf = NULL, *sbuf = NULL, *cfilter; int buflen = 0, nbuf = 0, fbuf; st_filter_t f; MYSQL_SAFE(buf, 24 + strlen(owner), buflen); nbuf = sprintf(buf, "`collection-owner` = '%s'", owner); sbuf = xhash_get(data->filters, filter); if(sbuf != NULL) { MYSQL_SAFE(buf, buflen + strlen(sbuf) + 7, buflen); nbuf += sprintf(&buf[nbuf], " AND %s", sbuf); return buf; } cfilter = pstrdup(xhash_pool(data->filters), filter); f = storage_filter(filter); if(f == NULL) return buf; MYSQL_SAFE(buf, buflen + 5, buflen); nbuf += sprintf(&buf[nbuf], " AND "); fbuf = nbuf; _st_mysql_convert_filter_recursive(drv, f, &buf, &buflen, &nbuf); xhash_put(data->filters, cfilter, pstrdup(xhash_pool(data->filters), &buf[fbuf])); pool_free(f->p); return buf;}static st_ret_t _st_mysql_add_type(st_driver_t drv, const char *type) { return st_SUCCESS;}static st_ret_t _st_mysql_put_guts(st_driver_t drv, const char *type, const char *owner, os_t os) { drvdata_t data = (drvdata_t) drv->private; char *left = NULL, *right = NULL; int lleft = 0, lright = 0, nleft, nright; os_object_t o; char *key, *cval = NULL; void *val; int vlen; os_type_t ot; char *xml; int xlen; char tbuf[128]; if(os_count(os) == 0) return st_SUCCESS; if(data->prefix != NULL) { snprintf(tbuf, sizeof(tbuf), "%s%s", data->prefix, type); type = tbuf; } if(os_iter_first(os)) do { MYSQL_SAFE(left, strlen(type) + 36, lleft); nleft = sprintf(left, "INSERT INTO `%s` ( `collection-owner`", type); MYSQL_SAFE(right, strlen(owner) + 15, lright); nright = sprintf(right, " ) VALUES ( '%s'", owner); o = os_iter_object(os); if(os_object_iter_first(o)) do { os_object_iter_get(o, &key, &val, &ot); switch(ot) { case os_type_BOOLEAN: cval = val ? strdup("1") : strdup("0"); vlen = 1; break; case os_type_INTEGER: cval = (char *) malloc(sizeof(char) * 20); sprintf(cval, "%d", (int) val); vlen = strlen(cval); break; case os_type_STRING: cval = (char *) malloc(sizeof(char) * ((strlen((char *) val) * 2) + 1)); vlen = mysql_real_escape_string(data->conn, cval, (char *) val, strlen((char *) val)); break; /* !!! might not be a good idea to mark nads this way */ case os_type_NAD: nad_print((nad_t) val, 0, &xml, &xlen); cval = (char *) malloc(sizeof(char) * ((xlen * 2) + 4)); vlen = mysql_real_escape_string(data->conn, &cval[3], xml, xlen) + 3; strncpy(cval, "NAD", 3); break; } log_debug(ZONE, "key %s val %s", key, cval); MYSQL_SAFE(left, lleft + strlen(key) + 4, lleft); nleft += sprintf(&left[nleft], ", `%s`", key); MYSQL_SAFE(right, lright + strlen(cval) + 4, lright); nright += sprintf(&right[nright], ", '%s'", cval); free(cval); } while(os_object_iter_next(o)); MYSQL_SAFE(left, lleft + strlen(right) + 2, lleft); sprintf(&left[nleft], "%s )", right); log_debug(ZONE, "prepared sql: %s", left); if(mysql_query(data->conn, left) != 0) { log_write(drv->st->sm->log, LOG_ERR, "mysql: sql insert failed: %s", mysql_error(data->conn)); free(left); free(right); return st_FAILED; } } while(os_iter_next(os)); free(left); free(right); return st_SUCCESS;}static st_ret_t _st_mysql_put(st_driver_t drv, const char *type, const char *owner, os_t os) { drvdata_t data = (drvdata_t) drv->private; if(os_count(os) == 0) return st_SUCCESS; if(mysql_ping(data->conn) != 0) { log_write(drv->st->sm->log, LOG_ERR, "mysql: connection to database lost"); return st_FAILED; } if(data->txn) { if(mysql_query(data->conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE") != 0) { log_write(drv->st->sm->log, LOG_ERR, "mysql: sql transaction setup failed: %s", mysql_error(data->conn)); return st_FAILED; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -