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); }
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); }
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); }
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); }
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 } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }
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); }
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); }