Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

dlr_mysql.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * dlr_mysql.c
00059  *
00060  * Implementation of handling delivery reports (DLRs)
00061  * for MySql database
00062  *
00063  * Andreas Fink <andreas@fink.org>, 18.08.2001
00064  * Stipe Tolj <stolj@wapme.de>, 22.03.2002
00065  * Alexander Malysh <a.malysh@centrium.de> 2003
00066 */
00067 
00068 #include "gwlib/gwlib.h"
00069 #include "gwlib/dbpool.h"
00070 #include "dlr_p.h"
00071 
00072 
00073 #ifdef HAVE_MYSQL
00074 #include <mysql/mysql.h>
00075 
00076 /*
00077  * Our connection pool to mysql.
00078  */
00079 static DBPool *pool = NULL;
00080 
00081 /*
00082  * Database fields, which we are use.
00083  */
00084 static struct dlr_db_fields *fields = NULL;
00085 
00086 
00087 static void mysql_update(const Octstr *sql)
00088 {
00089     int state;
00090     DBPoolConn *pc;
00091 
00092 #if defined(DLR_TRACE)
00093      debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
00094 #endif
00095 
00096     pc = dbpool_conn_consume(pool);
00097     if (pc == NULL) {
00098         error(0, "MYSQL: Database pool got no connection! DB update failed!");
00099         return;
00100     }
00101 
00102     state = mysql_query(pc->conn, octstr_get_cstr(sql));
00103     if (state != 0)
00104         error(0, "MYSQL: %s", mysql_error(pc->conn));
00105 
00106     dbpool_conn_produce(pc);
00107 }
00108 
00109 static MYSQL_RES* mysql_select(const Octstr *sql)
00110 {
00111     int state;
00112     MYSQL_RES *result = NULL;
00113     DBPoolConn *pc;
00114 
00115 #if defined(DLR_TRACE)
00116     debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
00117 #endif
00118 
00119     pc = dbpool_conn_consume(pool);
00120     if (pc == NULL) {
00121         error(0, "MYSQL: Database pool got no connection! DB update failed!");
00122         return NULL;
00123     }
00124 
00125     state = mysql_query(pc->conn, octstr_get_cstr(sql));
00126     if (state != 0) {
00127         error(0, "MYSQL: %s", mysql_error(pc->conn));
00128     } else {
00129         result = mysql_store_result(pc->conn);
00130     }
00131 
00132     dbpool_conn_produce(pc);
00133 
00134     return result;
00135 }
00136 
00137 static void dlr_mysql_shutdown()
00138 {
00139     dbpool_destroy(pool);
00140     dlr_db_fields_destroy(fields);
00141 }
00142 
00143 static void dlr_mysql_add(struct dlr_entry *entry)
00144 {
00145     Octstr *sql;
00146 
00147     sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES "
00148                         "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%d');",
00149                         octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
00150                         octstr_get_cstr(fields->field_ts),
00151                         octstr_get_cstr(fields->field_src), octstr_get_cstr(fields->field_dst),
00152                         octstr_get_cstr(fields->field_serv), octstr_get_cstr(fields->field_url),
00153                         octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_boxc),
00154                         octstr_get_cstr(fields->field_status),
00155                         octstr_get_cstr(entry->smsc), octstr_get_cstr(entry->timestamp), octstr_get_cstr(entry->source),
00156                         octstr_get_cstr(entry->destination), octstr_get_cstr(entry->service), octstr_get_cstr(entry->url),
00157                         entry->mask, octstr_get_cstr(entry->boxc_id), 0);
00158 
00159 
00160     mysql_update(sql);
00161 
00162     octstr_destroy(sql);
00163     dlr_entry_destroy(entry);
00164 }
00165 
00166 static struct dlr_entry* dlr_mysql_get(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
00167 {
00168     struct dlr_entry *res = NULL;
00169     Octstr *sql;
00170     MYSQL_RES *result;
00171     MYSQL_ROW row;
00172 
00173     sql = octstr_format("SELECT %s, %s, %s, %s, %s, %s FROM %s WHERE %s='%s' AND %s='%s';",
00174                         octstr_get_cstr(fields->field_mask), octstr_get_cstr(fields->field_serv),
00175                         octstr_get_cstr(fields->field_url), octstr_get_cstr(fields->field_src),
00176                         octstr_get_cstr(fields->field_dst), octstr_get_cstr(fields->field_boxc),
00177                         octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
00178                         octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
00179 
00180 
00181     result = mysql_select(sql);
00182     octstr_destroy(sql);
00183 
00184     if (result == NULL) {
00185         return NULL;
00186     }
00187     if (mysql_num_rows(result) < 1) {
00188         debug("dlr.mysql", 0, "no rows found");
00189         mysql_free_result(result);
00190         return NULL;
00191     }
00192     row = mysql_fetch_row(result);
00193     if (!row) {
00194         debug("dlr.mysql", 0, "rows found but could not load them");
00195         mysql_free_result(result);
00196         return NULL;
00197     }
00198 
00199     debug("dlr.mysql", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, row[3]=%s, row[4]=%s row[5]=%s",
00200           row[0], row[1], row[2], (row[3] ? row[3] : "NULL"), (row[4] ? row[4] : "NULL"), (row[5] ? row[5] : "NULL"));
00201 
00202     res = dlr_entry_create();
00203     gw_assert(res != NULL);
00204     res->mask = atoi(row[0]);
00205     res->service = octstr_create(row[1]);
00206     res->url = octstr_create(row[2]);
00207     res->source = row[3] ? octstr_create(row[3]) : octstr_create("");
00208     res->destination = row[4] ? octstr_create(row[4]) : octstr_create("");
00209     res->boxc_id = row[5] ? octstr_create(row[5]) : octstr_create("");
00210     res->smsc = octstr_duplicate(smsc);
00211 
00212     mysql_free_result(result);
00213 
00214     return res;
00215 }
00216 
00217 static void dlr_mysql_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
00218 {
00219     Octstr *sql;
00220 
00221     debug("dlr.mysql", 0, "removing DLR from database");
00222     sql = octstr_format("DELETE FROM %s WHERE %s='%s' AND %s='%s' LIMIT 1;",
00223                         octstr_get_cstr(fields->table), octstr_get_cstr(fields->field_smsc),
00224                         octstr_get_cstr(smsc), octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
00225 
00226 
00227     mysql_update(sql);
00228 
00229     octstr_destroy(sql);
00230 }
00231 
00232 static void dlr_mysql_update(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
00233 {
00234     Octstr *sql;
00235 
00236     debug("dlr.mysql", 0, "updating DLR status in database");
00237     sql = octstr_format("UPDATE %s SET %s=%d WHERE %s='%s' AND %s='%s' LIMIT 1;",
00238                         octstr_get_cstr(fields->table),
00239                         octstr_get_cstr(fields->field_status), status,
00240                         octstr_get_cstr(fields->field_smsc), octstr_get_cstr(smsc),
00241                         octstr_get_cstr(fields->field_ts), octstr_get_cstr(ts));
00242 
00243     mysql_update(sql);
00244 
00245     octstr_destroy(sql);
00246 }
00247 
00248 
00249 static long dlr_mysql_messages(void)
00250 {
00251     Octstr *sql;
00252     long res;
00253     MYSQL_RES *result;
00254     MYSQL_ROW row;
00255 
00256     sql = octstr_format("SELECT count(*) FROM %s;", octstr_get_cstr(fields->table));
00257 
00258     result = mysql_select(sql);
00259     octstr_destroy(sql);
00260 
00261     if (result == NULL) {
00262         return -1;
00263     }
00264     if (mysql_num_rows(result) < 1) {
00265         debug("dlr.mysql", 0, "Could not get count of DLR table");
00266         mysql_free_result(result);
00267         return 0;
00268     }
00269     row = mysql_fetch_row(result);
00270     if (row == NULL) {
00271         debug("dlr.mysql", 0, "rows found but could not load them");
00272         mysql_free_result(result);
00273         return 0;
00274     }
00275     res = atol(row[0]);
00276     mysql_free_result(result);
00277 
00278     return res;
00279 }
00280 
00281 static void dlr_mysql_flush(void)
00282 {
00283     Octstr *sql;
00284 
00285     sql = octstr_format("DELETE FROM %s;", octstr_get_cstr(fields->table));
00286 
00287     mysql_update(sql);
00288     octstr_destroy(sql);
00289 }
00290 
00291 static struct dlr_storage handles = {
00292     .type = "mysql",
00293     .dlr_add = dlr_mysql_add,
00294     .dlr_get = dlr_mysql_get,
00295     .dlr_update = dlr_mysql_update,
00296     .dlr_remove = dlr_mysql_remove,
00297     .dlr_shutdown = dlr_mysql_shutdown,
00298     .dlr_messages = dlr_mysql_messages,
00299     .dlr_flush = dlr_mysql_flush
00300 };
00301 
00302 struct dlr_storage *dlr_init_mysql(Cfg *cfg)
00303 {
00304     CfgGroup *grp;
00305     List *grplist;
00306     Octstr *mysql_host, *mysql_user, *mysql_pass, *mysql_db, *mysql_id;
00307     long mysql_port = 0;
00308     Octstr *p = NULL;
00309     long pool_size;
00310     DBConf *db_conf = NULL;
00311 
00312     /*
00313      * check for all mandatory directives that specify the field names
00314      * of the used MySQL table
00315      */
00316     if (!(grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))))
00317         panic(0, "DLR: MySQL: group 'dlr-db' is not specified!");
00318 
00319     if (!(mysql_id = cfg_get(grp, octstr_imm("id"))))
00320         panic(0, "DLR: MySQL: directive 'id' is not specified!");
00321 
00322     fields = dlr_db_fields_create(grp);
00323     gw_assert(fields != NULL);
00324 
00325     /*
00326      * now grap the required information from the 'mysql-connection' group
00327      * with the mysql-id we just obtained
00328      *
00329      * we have to loop through all available MySQL connection definitions
00330      * and search for the one we are looking for
00331      */
00332 
00333     grplist = cfg_get_multi_group(cfg, octstr_imm("mysql-connection"));
00334     while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
00335         p = cfg_get(grp, octstr_imm("id"));
00336         if (p != NULL && octstr_compare(p, mysql_id) == 0) {
00337             goto found;
00338         }
00339         if (p != NULL) octstr_destroy(p);
00340     }
00341     panic(0, "DLR: MySQL: connection settings for id '%s' are not specified!",
00342           octstr_get_cstr(mysql_id));
00343 
00344 found:
00345     octstr_destroy(p);
00346     gwlist_destroy(grplist, NULL);
00347 
00348     if (cfg_get_integer(&pool_size, grp, octstr_imm("max-connections")) == -1 || pool_size == 0)
00349         pool_size = 1;
00350 
00351     if (!(mysql_host = cfg_get(grp, octstr_imm("host"))))
00352         panic(0, "DLR: MySQL: directive 'host' is not specified!");
00353     if (!(mysql_user = cfg_get(grp, octstr_imm("username"))))
00354         panic(0, "DLR: MySQL: directive 'username' is not specified!");
00355     if (!(mysql_pass = cfg_get(grp, octstr_imm("password"))))
00356         panic(0, "DLR: MySQL: directive 'password' is not specified!");
00357     if (!(mysql_db = cfg_get(grp, octstr_imm("database"))))
00358         panic(0, "DLR: MySQL: directive 'database' is not specified!");
00359     cfg_get_integer(&mysql_port, grp, octstr_imm("port"));  /* optional */
00360 
00361     /*
00362      * ok, ready to connect to MySQL
00363      */
00364     db_conf = gw_malloc(sizeof(DBConf));
00365     gw_assert(db_conf != NULL);
00366 
00367     db_conf->mysql = gw_malloc(sizeof(MySQLConf));
00368     gw_assert(db_conf->mysql != NULL);
00369 
00370     db_conf->mysql->host = mysql_host;
00371     db_conf->mysql->port = mysql_port;
00372     db_conf->mysql->username = mysql_user;
00373     db_conf->mysql->password = mysql_pass;
00374     db_conf->mysql->database = mysql_db;
00375 
00376     pool = dbpool_create(DBPOOL_MYSQL, db_conf, pool_size);
00377     gw_assert(pool != NULL);
00378 
00379     /*
00380      * XXX should a failing connect throw panic?!
00381      */
00382     if (dbpool_conn_count(pool) == 0)
00383         panic(0,"DLR: MySQL: database pool has no connections!");
00384 
00385     octstr_destroy(mysql_id);
00386 
00387     return &handles;
00388 }
00389 #else
00390 /*
00391  * Return NULL , so we point dlr-core that we were
00392  * not compiled in.
00393  */
00394 struct dlr_storage *dlr_init_mysql(Cfg* cfg)
00395 {
00396     return NULL;
00397 }
00398 #endif /* HAVE_MYSQL */
00399 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.