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

dlr_oracle.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_oracle.c - Oracle dlr storage implementation.
00059  *
00060  * Author: Alexander Malysh <a.malysh@centrium.de>, (C) 2003
00061  * Robert Gałach <robert.galach@my.tenbit.pl>
00062  *      2004 Rewrited sql queries to use binding variables.
00063  *
00064  * Copyright: See COPYING file that comes with this distribution
00065  */
00066 
00067 #include "gwlib/gwlib.h"
00068 #include "gwlib/dbpool.h"
00069 #include "dlr_p.h"
00070 
00071 
00072 #ifdef HAVE_ORACLE
00073 
00074 /*
00075  * Our connection pool to oracle.
00076  */
00077 static DBPool *pool = NULL;
00078 
00079 /*
00080  * Database fields, which we are use.
00081  */
00082 static struct dlr_db_fields *fields = NULL;
00083 
00084 
00085 static long dlr_messages_oracle()
00086 {
00087     List *result, *row;
00088     Octstr *sql;
00089     DBPoolConn *conn;
00090     long msgs = -1;
00091 
00092     conn = dbpool_conn_consume(pool);
00093     if (conn == NULL)
00094         return -1;
00095 
00096     sql = octstr_format("SELECT count(*) FROM %S", fields->table);
00097 #if defined(DLR_TRACE)
00098     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
00099 #endif
00100 
00101     if (dbpool_conn_select(conn, sql, NULL, &result) != 0) {
00102         octstr_destroy(sql);
00103         dbpool_conn_produce(conn);
00104         return -1;
00105     }
00106     dbpool_conn_produce(conn);
00107     octstr_destroy(sql);
00108 
00109     if (gwlist_len(result) > 0) {
00110         row = gwlist_extract_first(result);
00111         msgs = strtol(octstr_get_cstr(gwlist_get(row,0)), NULL, 10);
00112         gwlist_destroy(row, octstr_destroy_item);
00113     }
00114     gwlist_destroy(result, NULL);
00115 
00116     return msgs;
00117 }
00118 
00119 static void dlr_shutdown_oracle()
00120 {
00121     dbpool_destroy(pool);
00122     dlr_db_fields_destroy(fields);
00123 }
00124 
00125 static void dlr_add_oracle(struct dlr_entry *entry)
00126 {
00127     Octstr *sql, *os_mask;
00128     DBPoolConn *pconn;
00129     List *binds = gwlist_create();
00130     debug("dlr.oracle", 0, "adding DLR entry into database");
00131 
00132     pconn = dbpool_conn_consume(pool);
00133     /* just for sure */
00134     if (pconn == NULL) {
00135         dlr_entry_destroy(entry);
00136         return;
00137     }
00138 
00139     sql = octstr_format("INSERT INTO %S (%S, %S, %S, %S, %S, %S, %S, %S, %S) VALUES "
00140                         "(:1, :2, :3, :4, :5, :6, :7, :8, 0)",
00141                         fields->table, fields->field_smsc, fields->field_ts,
00142                         fields->field_src, fields->field_dst, fields->field_serv, 
00143                         fields->field_url, fields->field_mask, fields->field_boxc,
00144                         fields->field_status);
00145     os_mask = octstr_format("%d", entry->mask);
00146     
00147     gwlist_append(binds, entry->smsc);         /* :1 */
00148     gwlist_append(binds, entry->timestamp);    /* :2 */
00149     gwlist_append(binds, entry->source);       /* :3 */
00150     gwlist_append(binds, entry->destination);  /* :4 */
00151     gwlist_append(binds, entry->service);      /* :5 */
00152     gwlist_append(binds, entry->url);          /* :6 */
00153     gwlist_append(binds, os_mask);             /* :7 */
00154     gwlist_append(binds, entry->boxc_id);      /* :8 */
00155 #if defined(DLR_TRACE)
00156     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
00157 #endif
00158     if (dbpool_conn_update(pconn, sql, binds) == -1)
00159         error(0, "DLR: ORACLE: Error while adding dlr entry for DST<%s>", octstr_get_cstr(entry->destination));
00160 
00161     dbpool_conn_produce(pconn);
00162     octstr_destroy(sql);
00163     gwlist_destroy(binds, NULL);
00164     octstr_destroy(os_mask);
00165     dlr_entry_destroy(entry);
00166 }
00167 
00168 static void dlr_remove_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
00169 {
00170     Octstr *sql;
00171     DBPoolConn *pconn;
00172     List *binds = gwlist_create();
00173 
00174     debug("dlr.oracle", 0, "removing DLR from database");
00175 
00176     pconn = dbpool_conn_consume(pool);
00177     /* just for sure */
00178     if (pconn == NULL)
00179         return;
00180 
00181     sql = octstr_format("DELETE FROM %S WHERE %S=:1 AND %S=:2 AND %S=:3 AND ROWNUM < 2",
00182                         fields->table, fields->field_smsc,
00183                         fields->field_ts, fields->field_dst);
00184 
00185     gwlist_append(binds, (Octstr *)smsc);      /* :1 */
00186     gwlist_append(binds, (Octstr *)ts);        /* :2 */
00187     gwlist_append(binds, (Octstr *)dst);       /* :3 */
00188 
00189 #if defined(DLR_TRACE)
00190     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
00191 #endif
00192 
00193     if (dbpool_conn_update(pconn, sql, binds) == -1)
00194         error(0, "DLR: ORACLE: Error while removing dlr entry for DST<%s>", octstr_get_cstr(dst));
00195 
00196     dbpool_conn_produce(pconn);
00197     gwlist_destroy(binds, NULL);
00198     octstr_destroy(sql);
00199 }
00200 
00201 static struct dlr_entry* dlr_get_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
00202 {
00203     Octstr *sql;
00204     DBPoolConn *pconn;
00205     List *result = NULL, *row;
00206     struct dlr_entry *res = NULL;
00207     List *binds = gwlist_create();
00208 
00209     pconn = dbpool_conn_consume(pool);
00210     if (pconn == NULL) /* should not happens, but sure is sure */
00211         return NULL;
00212 
00213     sql = octstr_format("SELECT %S, %S, %S, %S, %S, %S FROM %S WHERE %S=:1 AND %S=:2 AND %S=:3 AND ROWNUM < 2",
00214                         fields->field_mask, fields->field_serv,
00215                         fields->field_url, fields->field_src,
00216                         fields->field_dst, fields->field_boxc,
00217                         fields->table, fields->field_smsc,
00218                         fields->field_ts, fields->field_dst);
00219 
00220     gwlist_append(binds, (Octstr *)smsc);      /* :1 */
00221     gwlist_append(binds, (Octstr *)ts);        /* :2 */
00222     gwlist_append(binds, (Octstr *)dst);       /* :3 */
00223 
00224 #if defined(DLR_TRACE)
00225     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
00226 #endif
00227     if (dbpool_conn_select(pconn, sql, binds, &result) != 0) {
00228         octstr_destroy(sql);
00229         dbpool_conn_produce(pconn);
00230         return NULL;
00231     }
00232     octstr_destroy(sql);
00233     gwlist_destroy(binds, NULL);
00234     dbpool_conn_produce(pconn);
00235 
00236 #define LO2CSTR(r, i) octstr_get_cstr(gwlist_get(r, i))
00237 
00238     if (gwlist_len(result) > 0) {
00239         row = gwlist_extract_first(result);
00240         res = dlr_entry_create();
00241         gw_assert(res != NULL);
00242         res->mask = atoi(LO2CSTR(row,0));
00243         res->service = octstr_create(LO2CSTR(row, 1));
00244         res->url = octstr_create(LO2CSTR(row,2));
00245         res->source = octstr_create(LO2CSTR(row, 3));
00246         res->destination = octstr_create(LO2CSTR(row, 4));
00247         res->boxc_id = octstr_create(LO2CSTR(row, 5));
00248         gwlist_destroy(row, octstr_destroy_item);
00249         res->smsc = octstr_duplicate(smsc);
00250     }
00251     gwlist_destroy(result, NULL);
00252 
00253 #undef LO2CSTR
00254 
00255     return res;
00256 }
00257 
00258 static void dlr_update_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
00259 {
00260     Octstr *sql, *os_status;
00261     DBPoolConn *pconn;
00262     List *binds = gwlist_create();
00263 
00264     debug("dlr.oracle", 0, "updating DLR status in database");
00265 
00266     pconn = dbpool_conn_consume(pool);
00267     /* just for sure */
00268     if (pconn == NULL)
00269         return;
00270 
00271     sql = octstr_format("UPDATE %S SET %S=:1 WHERE %S=:2 AND %S=:3 AND %S=:4 AND ROWNUM < 2",
00272                         fields->table, fields->field_status,
00273                         fields->field_smsc, fields->field_ts, fields->field_dst);
00274 
00275     os_status = octstr_format("%d", status);
00276     gwlist_append(binds, (Octstr *)os_status); /* :1 */
00277     gwlist_append(binds, (Octstr *)smsc);      /* :2 */
00278     gwlist_append(binds, (Octstr *)ts);        /* :3 */
00279     gwlist_append(binds, (Octstr *)dst);       /* :4 */
00280 #if defined(DLR_TRACE)
00281     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
00282 #endif
00283     if (dbpool_conn_update(pconn, sql, binds) == -1)
00284         error(0, "DLR: ORACLE: Error while updating dlr entry for DST<%s>", octstr_get_cstr(dst));
00285 
00286     dbpool_conn_produce(pconn);
00287     gwlist_destroy(binds, NULL);
00288     octstr_destroy(os_status);
00289     octstr_destroy(sql);
00290 }
00291 
00292 static void dlr_flush_oracle (void)
00293 {
00294     Octstr *sql;
00295     DBPoolConn *pconn;
00296     int rows;
00297 
00298     pconn = dbpool_conn_consume(pool);
00299     /* just for sure */
00300     if (pconn == NULL)
00301         return;
00302 
00303     sql = octstr_format("DELETE FROM DLR");
00304 #if defined(DLR_TRACE)
00305     debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
00306 #endif
00307     rows = dbpool_conn_update(pconn, sql, NULL);
00308     if (rows == -1)
00309         error(0, "DLR: ORACLE: Error while flushing dlr entries from database");
00310     else
00311         debug("dlr.oracle", 0, "Flushing %d DLR entries from database", rows);
00312     dbpool_conn_produce(pconn);
00313     octstr_destroy(sql);
00314 }
00315 
00316 static struct dlr_storage handles = {
00317     .type = "oracle",
00318     .dlr_messages = dlr_messages_oracle,
00319     .dlr_shutdown = dlr_shutdown_oracle,
00320     .dlr_add = dlr_add_oracle,
00321     .dlr_get = dlr_get_oracle,
00322     .dlr_remove = dlr_remove_oracle,
00323     .dlr_update = dlr_update_oracle,
00324     .dlr_flush = dlr_flush_oracle
00325 };
00326 
00327 struct dlr_storage *dlr_init_oracle(Cfg *cfg)
00328 {
00329     CfgGroup *grp;
00330     List *grplist;
00331     long pool_size;
00332     DBConf *db_conf = NULL;
00333     Octstr *id, *username, *password, *tnsname;
00334     int found;
00335 
00336     if ((grp = cfg_get_single_group(cfg, octstr_imm("dlr-db"))) == NULL)
00337         panic(0, "DLR: ORACLE: group 'dlr-db' is not specified!");
00338 
00339     if (!(id = cfg_get(grp, octstr_imm("id"))))
00340     panic(0, "DLR: ORACLE: directive 'id' is not specified!");
00341 
00342     /* initialize database fields */
00343     fields = dlr_db_fields_create(grp);
00344     gw_assert(fields != NULL);
00345 
00346     grplist = cfg_get_multi_group(cfg, octstr_imm("oracle-connection"));
00347     found = 0;
00348     while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
00349         Octstr *p = cfg_get(grp, octstr_imm("id"));
00350         if (p != NULL && octstr_compare(p, id) == 0) {
00351             found = 1;
00352         }
00353         if (p != NULL) 
00354             octstr_destroy(p);
00355         if (found == 1) 
00356             break;
00357     }
00358     gwlist_destroy(grplist, NULL);
00359 
00360     if (found == 0)
00361         panic(0, "DLR: ORACLE: connection settings for id '%s' are not specified!",
00362               octstr_get_cstr(id));
00363 
00364     username = cfg_get(grp, octstr_imm("username"));
00365     password = cfg_get(grp, octstr_imm("password"));
00366     tnsname = cfg_get(grp, octstr_imm("tnsname"));
00367     if (cfg_get_integer(&pool_size, grp, octstr_imm("max-connections")) == -1)
00368         pool_size = 1;
00369 
00370     if (username == NULL || password == NULL || tnsname == NULL)
00371         panic(0, "DLR: ORACLE: connection settings missing for id '%s', please"
00372                       " check you configuration.",octstr_get_cstr(id));
00373 
00374     /* ok we are ready to create dbpool */
00375     db_conf = gw_malloc(sizeof(*db_conf));
00376     db_conf->oracle = gw_malloc(sizeof(OracleConf));
00377 
00378     db_conf->oracle->username = username;
00379     db_conf->oracle->password = password;
00380     db_conf->oracle->tnsname = tnsname;
00381 
00382     pool = dbpool_create(DBPOOL_ORACLE, db_conf, pool_size);
00383     gw_assert(pool != NULL);
00384 
00385     if (dbpool_conn_count(pool) == 0)
00386         panic(0, "DLR: ORACLE: Couldnot establish oracle connection(s).");
00387 
00388     octstr_destroy(id);
00389 
00390     return &handles;
00391 }
00392 #else
00393 /* no oracle support build in */
00394 struct dlr_storage *dlr_init_oracle(Cfg *cfg)
00395 {
00396     return NULL;
00397 }
00398 #endif /* HAVE_ORACLE */
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.