Example #1
0
static void dlr_update_oracle(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
{
    Octstr *sql, *os_status;
    DBPoolConn *pconn;
    List *binds = gwlist_create();

    debug("dlr.oracle", 0, "updating DLR status in database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL)
        return;

    sql = octstr_format("UPDATE %S SET %S=:1 WHERE %S=:2 AND %S=:3 AND %S=:4 AND ROWNUM < 2",
                        fields->table, fields->field_status,
                        fields->field_smsc, fields->field_ts, fields->field_dst);

    os_status = octstr_format("%d", status);
    gwlist_append(binds, (Octstr *)os_status); /* :1 */
    gwlist_append(binds, (Octstr *)smsc);      /* :2 */
    gwlist_append(binds, (Octstr *)ts);        /* :3 */
    gwlist_append(binds, (Octstr *)dst);       /* :4 */
#if defined(DLR_TRACE)
    debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    if (dbpool_conn_update(pconn, sql, binds) == -1)
        error(0, "DLR: ORACLE: Error while updating dlr entry for DST<%s>", octstr_get_cstr(dst));

    dbpool_conn_produce(pconn);
    gwlist_destroy(binds, NULL);
    octstr_destroy(os_status);
    octstr_destroy(sql);
}
Example #2
0
static void dlr_update_mssql(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
{
    Octstr *sql, *like;
    DBPoolConn *pconn;
    int res;

    debug("dlr.mssql", 0, "updating DLR status in database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL)
        return;

    if (dst)
        like = octstr_format("AND %S LIKE '%%%S'", fields->field_dst, dst);
    else
        like = octstr_imm("");

    sql = octstr_format("SET ROWCOUNT 1\nUPDATE %S SET %S=%d WHERE %S='%S' "
        "AND %S='%S' %S\nSET ROWCOUNT 0",
        fields->table, fields->field_status, status, fields->field_smsc, smsc,
        fields->field_ts, ts, like);

#if defined(DLR_TRACE)
    debug("dlr.mssql", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    if ((res = dbpool_conn_update(pconn, sql, NULL)) == -1)
        error(0, "DLR: MSSQL: Error while updating dlr entry for DST<%s>", octstr_get_cstr(dst));
    else if (!res)
        warning(0, "DLR: MSSQL: No dlr found to update for DST<%s> (status: %d)", octstr_get_cstr(dst), status);

    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
    octstr_destroy(like);
}
Example #3
0
static void dlr_remove_mssql(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
{
    Octstr *sql, *like;
    DBPoolConn *pconn;
    int res;

    debug("dlr.mssql", 0, "removing DLR from database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL)
        return;

    if (dst)
        like = octstr_format("AND %S LIKE '%%%S'", fields->field_dst, dst);
    else
        like = octstr_imm("");

    sql = octstr_format("SET ROWCOUNT 1\nDELETE FROM %S WHERE %S='%S' AND "
         "%S='%S' %S \nSET ROWCOUNT 0", fields->table, fields->field_smsc,
         smsc, fields->field_ts, ts, like);

#if defined(DLR_TRACE)
    debug("dlr.mssql", 0, "sql: %s", octstr_get_cstr(sql));
#endif

    if ((res = dbpool_conn_update(pconn, sql, NULL)) == -1)
        error(0, "DLR: MSSQL: Error while removing dlr entry for DST<%s>", octstr_get_cstr(dst));
    else if (!res)
        warning(0, "DLR: MSSQL: No dlr deleted for DST<%s>", octstr_get_cstr(dst));

    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
    octstr_destroy(like);
}
Example #4
0
static void dlr_add_mssql(struct dlr_entry *entry)
{
    Octstr *sql;
    DBPoolConn *pconn;
    debug("dlr.mssql", 0, "adding DLR entry into database");
    int res;

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL) {
        dlr_entry_destroy(entry);
        return;
    }
    
    sql = octstr_format("INSERT INTO %S (%S, %S, %S, %S, %S, %S, %S, %S, %S) VALUES "
                "('%S', '%S', '%S', '%S', '%S', '%S', '%d', '%S', '%d')",
                fields->table, fields->field_smsc, fields->field_ts, fields->field_src,
                fields->field_dst, fields->field_serv, fields->field_url,
                fields->field_mask, fields->field_boxc, fields->field_status,
                entry->smsc, entry->timestamp, entry->source, entry->destination,
                entry->service, entry->url, entry->mask, entry->boxc_id, 0);

#if defined(DLR_TRACE)
    debug("dlr.mssql", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    if ((res = dbpool_conn_update(pconn, sql, NULL)) == -1)
        error(0, "DLR: MSSQL: Error while adding dlr entry for DST<%s>", octstr_get_cstr(entry->destination));
    else if (!res)
        warning(0, "DLR: MSSQL: No dlr inserted for DST<%s>", octstr_get_cstr(entry->destination));

    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
    dlr_entry_destroy(entry);
}
Example #5
0
static void oracle_client_thread(void *arg)
{
    DBPool *pool = arg;
    DBPoolConn *pconn = NULL;
    int i;
    List *result;

    for (i = 1; i <= queries; i++) {
        pconn = dbpool_conn_consume(pool);

        if (pconn == NULL)
            continue;
#if 1 /* selects */
        if (dbpool_conn_select(pconn, sql, NULL, &result) == 0) {
            long i,j;
            for (i=0; i < gwlist_len(result); i++) {
                List *row = gwlist_get(result, i);
                for (j=0; j < gwlist_len(row); j++)
                    debug("", 0, "col = %ld   value = '%s'", j, octstr_get_cstr(gwlist_get(row,j)));
                gwlist_destroy(row, octstr_destroy_item);
            }
        }
        gwlist_destroy(result, NULL);
        dbpool_conn_produce(pconn);
#else /* only updates */
        debug("", 0, "rows processed = %d ", dbpool_conn_update(pconn, sql, NULL));
        dbpool_conn_produce(pconn);
#endif
    }
}
Example #6
0
static void dlr_redis_remove(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
{
    Octstr *key, *sql;
    DBPoolConn *pconn;
    List *binds = gwlist_create();
    int res;

    debug("dlr.redis", 0, "Removing DLR from keystore");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL) {
        error(0, "DLR: REDIS: No connection available");
        gwlist_destroy(binds, NULL);
        return;
    }

    /*
    octstr_replace(dst, octstr_imm(" "), octstr_imm(""));
    octstr_replace(ts, octstr_imm(" "), octstr_imm(""));
    */

    key = octstr_format((dst ? "%S:?:?:?" : "%S:?:?"), fields->table);

    sql = octstr_format("DEL %S", key, fields->table);
    gwlist_append(binds, (Octstr *)smsc); /* key */
    gwlist_append(binds, (Octstr *)ts); /* key */
    if (dst)
        gwlist_append(binds, (Octstr *)dst); /* key */

    res = dbpool_conn_update(pconn, sql, binds);
 
    /*
     * Redis DEL returns the number of keys deleted
     */ 
    if (res != 1) {
        /* 
         * We may fail to delete a DLR that was successfully retrieved
         * just above due to race conditions when duplicate message IDs
         * are received. This happens frequently when testing via the
         * Logica SMPP emulator due to its duplicate message ID bugs.
         */
        error(0, "DLR: REDIS: Error while removing dlr entry for %s",
              octstr_get_cstr(key));
    }
    /* We don't perform 'DECR <table>:Count', since we have TTL'ed
     * expirations, which can't be handled with manual counters. */

    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
    octstr_destroy(key);
    gwlist_destroy(binds, NULL);
}
Example #7
0
static void dlr_mysql_add(struct dlr_entry *entry)
{
    Octstr *sql, *os_mask;
    DBPoolConn *pconn;
    List *binds = gwlist_create();
    int res;

    debug("dlr.mysql", 0, "adding DLR entry into database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL) {
        dlr_entry_destroy(entry);
        return;
    }

    sql = octstr_format("INSERT INTO `%S` (`%S`, `%S`, `%S`, `%S`, `%S`, `%S`, `%S`, `%S`, `%S`) VALUES "
                        "(?, ?, ?, ?, ?, ?, ?, ?, 0)",
                        fields->table, fields->field_smsc, fields->field_ts,
                        fields->field_src, fields->field_dst, fields->field_serv,
                        fields->field_url, fields->field_mask, fields->field_boxc,
                        fields->field_status);
    os_mask = octstr_format("%d", entry->mask);
    gwlist_append(binds, entry->smsc);
    gwlist_append(binds, entry->timestamp);
    gwlist_append(binds, entry->source);
    gwlist_append(binds, entry->destination);
    gwlist_append(binds, entry->service);
    gwlist_append(binds, entry->url);
    gwlist_append(binds, os_mask);
    gwlist_append(binds, entry->boxc_id);

#if defined(DLR_TRACE)
    debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    if ((res = dbpool_conn_update(pconn, sql, binds)) == -1)
        error(0, "DLR: MYSQL: Error while adding dlr entry for DST<%s>", octstr_get_cstr(entry->destination));
    else if (!res)
        warning(0, "DLR: MYSQL: No dlr inserted for DST<%s>", octstr_get_cstr(entry->destination));

    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
    gwlist_destroy(binds, NULL);
    octstr_destroy(os_mask);
    dlr_entry_destroy(entry);
}
Example #8
0
static void dlr_mysql_update(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
{
    Octstr *sql, *os_status, *like;
    DBPoolConn *pconn;
    List *binds = gwlist_create();
    int res;

    debug("dlr.mysql", 0, "updating DLR status in database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL)
        return;

    if (dst)
        like = octstr_format("AND `%S` LIKE CONCAT('%%', ?)", fields->field_dst);
    else
        like = octstr_imm("");

    sql = octstr_format("UPDATE `%S` SET `%S`=? WHERE `%S`=? AND `%S`=? %S LIMIT 1",
                        fields->table, fields->field_status,
                        fields->field_smsc, fields->field_ts,
                        like);

    os_status = octstr_format("%d", status);
    gwlist_append(binds, (Octstr *)os_status);
    gwlist_append(binds, (Octstr *)smsc);
    gwlist_append(binds, (Octstr *)ts);
    if (dst)
        gwlist_append(binds, (Octstr *)dst);

#if defined(DLR_TRACE)
    debug("dlr.mysql", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    if ((res = dbpool_conn_update(pconn, sql, binds)) == -1)
        error(0, "DLR: MYSQL: Error while updating dlr entry for DST<%s>", octstr_get_cstr(dst));
    else if (!res)
       warning(0, "DLR: MYSQL: No dlr found to update for DST<%s>, (status %d)", octstr_get_cstr(dst), status);

    dbpool_conn_produce(pconn);
    gwlist_destroy(binds, NULL);
    octstr_destroy(os_status);
    octstr_destroy(sql);
    octstr_destroy(like);
}
Example #9
0
static void dlr_update_sqlite3(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
{
    Octstr *sql, *os_status, *like;
    DBPoolConn *pconn;
    List *binds = gwlist_create();
    int res;

    debug("dlr.sqlite3", 0, "updating DLR status in database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL)
        return;

    if (dst)
        like = octstr_format("AND %S LIKE '%?4'", fields->field_dst);
    else
        like = octstr_imm("");

    sql = octstr_format("UPDATE %S SET %S=?1 WHERE ROWID IN (SELECT ROWID FROM %S WHERE %S=?2 AND %S=?3 %S LIMIT 1)",
                        fields->table, fields->field_status, fields->table,
                        fields->field_smsc, fields->field_ts, fields->field_dst);

    os_status = octstr_format("%d", status);
    gwlist_append(binds, (Octstr *)os_status); /* ?1 */
    gwlist_append(binds, (Octstr *)smsc);      /* ?2 */
    gwlist_append(binds, (Octstr *)ts);        /* ?3 */
    if (dst)
        gwlist_append(binds, (Octstr *)dst);   /* ?4 */
    
#if defined(DLR_TRACE)
    debug("dlr.sqlite3", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    if ((res = dbpool_conn_update(pconn, sql, binds)) == -1)
        error(0, "DLR: SQLite3: Error while updating dlr entry for DST<%s>", octstr_get_cstr(dst));
    else if (!res)
        warning(0, "DLR: SQLite3: No dlr found to update for DST<%s> (status: %d)", octstr_get_cstr(dst), status);

    dbpool_conn_produce(pconn);
    gwlist_destroy(binds, NULL);
    octstr_destroy(os_status);
    octstr_destroy(sql);
    octstr_destroy(like);
}
Example #10
0
static void dlr_redis_update(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int status)
{
    Octstr *key, *sql, *os_status;
    DBPoolConn *pconn;
    List *binds = gwlist_create();
    int res;

    debug("dlr.redis", 0, "Updating DLR status in keystore");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL) {
        error(0, "DLR: REDIS: No connection available");
        gwlist_destroy(binds, NULL);
        return;
    }

    os_status = octstr_format("%d", status);

    key = octstr_format((dst ? "%S:?:?:?" : "%S:?:?"), fields->table);

    sql = octstr_format("HSET %S %S ?", key, fields->field_status);
    gwlist_append(binds, (Octstr*)smsc);
    gwlist_append(binds, (Octstr*)ts);
    if (dst != NULL)
        gwlist_append(binds, (Octstr*)dst);
    gwlist_append(binds, os_status);

    if ((res = dbpool_conn_update(pconn, sql, binds)) == -1) {
        error(0, "DLR: REDIS: Error while updating dlr entry for %s",
              octstr_get_cstr(key));
    }
    else if (!res) {
        warning(0, "DLR: REDIS: No dlr found to update for %s",
                octstr_get_cstr(key));
    }

    dbpool_conn_produce(pconn);
    octstr_destroy(os_status);
    octstr_destroy(key);
    octstr_destroy(sql);
    gwlist_destroy(binds, NULL);
}
Example #11
0
static void dlr_add_oracle(struct dlr_entry *entry)
{
    Octstr *sql, *os_mask;
    DBPoolConn *pconn;
    List *binds = gwlist_create();
    debug("dlr.oracle", 0, "adding DLR entry into database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL) {
        dlr_entry_destroy(entry);
        return;
    }

    sql = octstr_format("INSERT INTO %S (%S, %S, %S, %S, %S, %S, %S, %S, %S) VALUES "
                        "(:1, :2, :3, :4, :5, :6, :7, :8, 0)",
                        fields->table, fields->field_smsc, fields->field_ts,
                        fields->field_src, fields->field_dst, fields->field_serv, 
                        fields->field_url, fields->field_mask, fields->field_boxc,
                        fields->field_status);
    os_mask = octstr_format("%d", entry->mask);
    
    gwlist_append(binds, entry->smsc);         /* :1 */
    gwlist_append(binds, entry->timestamp);    /* :2 */
    gwlist_append(binds, entry->source);       /* :3 */
    gwlist_append(binds, entry->destination);  /* :4 */
    gwlist_append(binds, entry->service);      /* :5 */
    gwlist_append(binds, entry->url);          /* :6 */
    gwlist_append(binds, os_mask);             /* :7 */
    gwlist_append(binds, entry->boxc_id);      /* :8 */
#if defined(DLR_TRACE)
    debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    if (dbpool_conn_update(pconn, sql, binds) == -1)
        error(0, "DLR: ORACLE: Error while adding dlr entry for DST<%s>", octstr_get_cstr(entry->destination));

    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
    gwlist_destroy(binds, NULL);
    octstr_destroy(os_mask);
    dlr_entry_destroy(entry);
}
Example #12
0
static void dlr_remove_sqlite3(const Octstr *smsc, const Octstr *ts, const Octstr *dst)
{
    Octstr *sql, *like;
    DBPoolConn *pconn;
    List *binds = gwlist_create();
    int res;
    debug("dlr.sqlite3", 0, "removing DLR from database");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL)
        return;
    
    if (dst)
        like = octstr_format("AND %S LIKE '%?3'", fields->field_dst);
    else
        like = octstr_imm("");

    sql = octstr_format("DELETE FROM %S WHERE ROWID IN (SELECT ROWID FROM %S WHERE %S=?1 AND %S=?2 %S LIMIT 1)",
                        fields->table, fields->table,
                        fields->field_smsc, fields->field_ts, like);

    gwlist_append(binds, (Octstr *)smsc);      /* ?1 */
    gwlist_append(binds, (Octstr *)ts);        /* ?2 */
    if (dst)
        gwlist_append(binds, (Octstr *)dst);   /* ?3 */

#if defined(DLR_TRACE)
    debug("dlr.sqlite3", 0, "sql: %s", octstr_get_cstr(sql));
#endif

    if ((res = dbpool_conn_update(pconn, sql, binds)) == -1)
        error(0, "DLR: SQLite3: Error while removing dlr entry for DST<%s>", octstr_get_cstr(dst));
    else if (!res)
        warning(0, "DLR: SQLite3: No dlr deleted for DST<%s>", octstr_get_cstr(dst));

    dbpool_conn_produce(pconn);
    gwlist_destroy(binds, NULL);
    octstr_destroy(sql);
    octstr_destroy(like);
}
Example #13
0
static inline int pgsql_update(const Octstr *sql)
{
    DBPoolConn *pc;
    int ret = 0;

#if defined(DLR_TRACE)
    debug("dlr.pgsql", 0, "sql: %s", octstr_get_cstr(sql));
#endif

    pc = dbpool_conn_consume(pool);
    if (pc == NULL) {
        error(0, "PGSQL: Database pool got no connection! DB update failed!");
        return -1;
    }

    if ((ret = dbpool_conn_update(pc, sql, NULL)) == -1)
        error(0, "PGSQL: DB update failed!");
    
    dbpool_conn_produce(pc);
    return ret;
}
Example #14
0
static void dlr_redis_flush(void)
{
    Octstr *sql;
    DBPoolConn *pconn;
    int rows;

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL) {
        error(0, "DLR: REDIS: No connection available");
        return;
    }

    sql = octstr_imm("FLUSHDB");
    rows = dbpool_conn_update(pconn, sql, NULL);
    if (rows == -1)
        error(0, "DLR: REDIS: Error while flushing dlr entries from database");
    else
        debug("dlr.redis", 0, "Flushed %d DLR entries from database", rows);
    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
}
Example #15
0
static void dlr_flush_oracle (void)
{
    Octstr *sql;
    DBPoolConn *pconn;
    int rows;

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL)
        return;

    sql = octstr_format("DELETE FROM DLR");
#if defined(DLR_TRACE)
    debug("dlr.oracle", 0, "sql: %s", octstr_get_cstr(sql));
#endif
    rows = dbpool_conn_update(pconn, sql, NULL);
    if (rows == -1)
        error(0, "DLR: ORACLE: Error while flushing dlr entries from database");
    else
        debug("dlr.oracle", 0, "Flushing %d DLR entries from database", rows);
    dbpool_conn_produce(pconn);
    octstr_destroy(sql);
}
Example #16
0
static void dlr_redis_add(struct dlr_entry *entry)
{
    Octstr *key, *sql, *os_mask;
    Octstr *dstclean, *srcclean, *tsclean;
    DBPoolConn *pconn;
    List *binds;
    int res, len;

    debug("dlr.redis", 0, "Adding DLR into keystore");

    pconn = dbpool_conn_consume(pool);
    /* just for sure */
    if (pconn == NULL) {
        error(0, "DLR: REDIS: No connection available - dropping DLR");
        dlr_entry_destroy(entry);
        return;
    }

    /*
     * This code is needed as we are mis-using the Hiredis API and
     * passing a fully-formed Redis command rather than tokenized
     * command components. Redis treats a space are a command delimiter
     * so any component that can include a space needs to be quoted.
     * Should be re-written to use the RedisCommandArgv() API.
     */

    dstclean = octstr_duplicate(entry->destination);
    octstr_replace(dstclean, octstr_imm(" "), octstr_imm("__space__"));

    srcclean = octstr_duplicate(entry->source);
    octstr_replace(srcclean, octstr_imm(" "), octstr_imm("__space__"));

    tsclean = octstr_duplicate(entry->timestamp);
    octstr_replace(tsclean, octstr_imm(" "), octstr_imm("__space__"));

    if (entry->use_dst && entry->destination) {
        Octstr *dst_min;

        /* keep a shorten version for the key part */
        dst_min = octstr_duplicate(dstclean);
        len = octstr_len(dst_min);
        if (len > MIN_DST_LEN)
            octstr_delete(dst_min, 0, len - MIN_DST_LEN);

        key = octstr_format("%S:%S:%S:%S", fields->table,
                entry->smsc,
                tsclean,
                dst_min);

        octstr_destroy(dst_min);
    } else {
        key = octstr_format("%S:%S:%S", fields->table,
                entry->smsc,
                tsclean);
    }

#ifdef REDIS_PRECHECK
    binds = gwlist_create();
    sql = octstr_format("HSETNX %S %S ?", key, fields->field_smsc);
    if (dbpool_conn_update(pconn, sql, binds) != 1) {
        error(0, "DLR: REDIS: DLR for %s already exists! Duplicate Message ID?",
              octstr_get_cstr(key));

        octstr_destroy(sql);
        octstr_destroy(key);
        octstr_destroy(tsclean);
        octstr_destroy(dstclean);
        octstr_destroy(srcclean);
        gwlist_destroy(binds, NULL);
        dbpool_conn_produce(pconn);
        return;
    }
    octstr_destroy(sql);
    gwlist_destroy(binds, NULL);
#endif

    binds = gwlist_create();
    sql = octstr_format("HMSET %S %S ? %S ? %S ? %S ? %S ? %S ? %S ? %S ? %S 0",
            key,
            fields->field_smsc,
            fields->field_ts,
            fields->field_src,
            fields->field_dst,
            fields->field_serv,
            fields->field_url,
            fields->field_mask,
            fields->field_boxc,
            fields->field_status);

    /* prepare values */
    if (entry->url) {
        octstr_url_encode(entry->url);
        octstr_replace(entry->url, octstr_imm("%"), octstr_imm("%%"));
    }
    os_mask = octstr_format("%d", entry->mask);

    gwlist_append(binds, entry->smsc);
    gwlist_append(binds, tsclean);
    gwlist_append(binds, srcclean);
    gwlist_append(binds, dstclean);
    gwlist_append(binds, entry->service);
    gwlist_append(binds, entry->url);
    gwlist_append(binds, os_mask);
    gwlist_append(binds, entry->boxc_id);

    res = dbpool_conn_update(pconn, sql, binds);

    if (res == -1) {
        error(0, "DLR: REDIS: Error while adding dlr entry %s:%s:%s:%s",
              octstr_get_cstr(fields->table),
              octstr_get_cstr(entry->smsc),
              octstr_get_cstr(tsclean),
              octstr_get_cstr(dstclean));
    }
    else  {
        /* HMSET returned OK. Set EXPIRE if applicable and then
         * increment the DLR counter */
        if (fields->ttl) {
            octstr_destroy(sql);
            sql = octstr_format("EXPIRE %S %ld", key, fields->ttl);
            res = dbpool_conn_update(pconn, sql, NULL);
        }
        /* We are not performing an 'INCR <table>:Count'
         * operation here, since we can't be accurate due
         * to TTL'ed expiration. Rather use 'DBSIZE' based
         * on seperated databases in redis. */
    }

    dbpool_conn_produce(pconn);
    octstr_destroy(os_mask);
    octstr_destroy(sql);
    octstr_destroy(key);
    octstr_destroy(tsclean);
    octstr_destroy(dstclean);
    octstr_destroy(srcclean);
    gwlist_destroy(binds, NULL);
    dlr_entry_destroy(entry);
}