]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-2050 Core ODBC support for transactions with MSSQL
authorJeff Lenk <jeff@jefflenk.com>
Thu, 21 Oct 2010 21:18:54 +0000 (16:18 -0500)
committerJeff Lenk <jeff@jefflenk.com>
Thu, 21 Oct 2010 21:18:54 +0000 (16:18 -0500)
conf/autoload_configs/switch.conf.xml
src/include/private/switch_core_pvt.h
src/include/switch_odbc.h
src/switch_core.c
src/switch_core_sqldb.c
src/switch_odbc.c

index e861b1b61a903745faa6500bf8d09abf007322f9..896dd0e712052b97968370557513945b8ab39577 100644 (file)
@@ -86,6 +86,7 @@
     <!-- <param name="core-db-dsn" value="dsn:username:password" /> -->
     <!-- The system will create all the db schemas automatically, set this to false to avoid this behaviour-->
     <!--<param name="auto-create-schemas" value="true"/>-->
+        <!-- <param name="core-dbtype" value="MSSQL"/> -->
   </settings>
 
 </configuration>
index ea02f22fa0fc551d4e48ac63e7e0eccf419a1278..3df9001b0cafcc140dc5040d893c69bd834a0160 100644 (file)
@@ -193,6 +193,11 @@ struct switch_media_bug {
        struct switch_media_bug *next;
 };
 
+typedef enum {
+       DBTYPE_DEFAULT = 0,
+       DBTYPE_MSSQL = 1,
+} switch_dbtype_t;
+
 struct switch_runtime {
        switch_time_t initiated;
        switch_time_t reference;
@@ -237,6 +242,7 @@ struct switch_runtime {
        double min_idle_time;
        int sql_buffer_len;
        int max_sql_buffer_len;
+       switch_dbtype_t odbc_dbtype;
 };
 
 extern struct switch_runtime runtime;
index 81039f113d9ef9685cc8b544ca697c633a6fd0a5..b8d4bc2f17920a93e6729bbfd96d06b24eb23737 100644 (file)
@@ -58,6 +58,8 @@ SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_
                                                                                                                         char **err);
 SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec_string(switch_odbc_handle_t *handle, const char *sql, char *resbuf, size_t len, char **err);
 SWITCH_DECLARE(switch_bool_t) switch_odbc_available(void);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit);
 SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_statement_handle_free(switch_odbc_statement_handle_t *stmt);
 
 /*!
index 2f89c7bca78d924186a30c92b7fe960b39b6d304..bd4b00d2ed3dc66f79d8e3651e4a6cab16641a5c 100644 (file)
@@ -1237,6 +1237,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
        runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION;
        runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION;
        runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION;
+       runtime.odbc_dbtype = DBTYPE_DEFAULT;
 
        /* INIT APR and Create the pool context */
        if (apr_initialize() != SWITCH_STATUS_SUCCESS) {
@@ -1590,6 +1591,12 @@ static void switch_load_core_config(const char *file)
                                        } else {
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
                                        }
+                               } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) {
+                                       if (!strcasecmp(val, "MSSQL")) {
+                                               runtime.odbc_dbtype = DBTYPE_MSSQL;
+                                       } else {
+                                               runtime.odbc_dbtype = DBTYPE_DEFAULT;
+                                       }
 #ifdef ENABLE_ZRTP
                                } else if (!strcasecmp(var, "rtp-enable-zrtp")) {
                                        switch_core_set_variable("zrtp_enabled", val);
index 7f995040e97b2fcbee079d4edd4d51bb50c7fa3d..a85766c60c5ae37c18a66a56f88bba6a259e55cb 100644 (file)
@@ -699,7 +699,13 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_
        while (begin_retries > 0) {
                again = 0;
 
-               switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg);
+               if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
+                       switch_cache_db_execute_sql_real(dbh, "BEGIN", &errmsg);
+               } else {
+                       if (switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 0) != SWITCH_ODBC_SUCCESS) {
+                               errmsg = strdup("Unable to Set AutoCommit Off.");;
+                       }
+               }
 
                if (errmsg) {
                        begin_retries--;
@@ -712,7 +718,13 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_
                        errmsg = NULL;
 
                        if (again) {
-                               switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
+                               if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
+                                       switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
+                               } else  {
+                                       switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1);
+                                       switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1);
+                               }
+
                                goto again;
                        }
 
@@ -750,7 +762,12 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_persistant_execute_trans(switch_
 
  done:
 
-       switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
+       if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
+               switch_cache_db_execute_sql_real(dbh, "COMMIT", NULL);
+       } else {
+               switch_odbc_SQLEndTran(dbh->native_handle.odbc_dbh, 1);
+               switch_odbc_SQLSetAutoCommitAttr(dbh->native_handle.odbc_dbh, 1);
+       }
 
        if (dbh->io_mutex) {
                switch_mutex_unlock(dbh->io_mutex);
@@ -1304,6 +1321,7 @@ static void core_event_handler(switch_event_t *event)
        case SWITCH_EVENT_CHANNEL_BRIDGE:
                {
                        const char *callee_cid_name, *callee_cid_num, *direction;
+                       char *func_name;
 
                        direction = switch_event_get_header(event, "other-leg-direction");
 
@@ -1319,10 +1337,19 @@ static void core_event_handler(switch_event_t *event)
                        new_sql() = switch_mprintf("update channels set call_uuid='%q' where uuid='%s' and hostname='%q'",
                                                                           switch_event_get_header_nil(event, "channel-call-uuid"),
                                                                           switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
-                       new_sql() = switch_mprintf("insert into calls (call_uuid,call_created,call_created_epoch,function,caller_cid_name,"
+
+                       if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
+                               func_name = "function";
+                       }
+                       else {
+                               func_name = "call_function";
+                       }
+
+                       new_sql() = switch_mprintf("insert into calls (call_uuid,call_created,call_created_epoch,%s,caller_cid_name,"
                                                                           "caller_cid_num,caller_dest_num,caller_chan_name,caller_uuid,callee_cid_name,"
                                                                           "callee_cid_num,callee_dest_num,callee_chan_name,callee_uuid,hostname) "
                                                                           "values ('%s', '%s', '%ld', '%s','%q','%q','%q','%q','%s','%q','%q','%q','%q','%s','%q')",
+                                                                          func_name,
                                                                           switch_event_get_header_nil(event, "channel-call-uuid"),
                                                                           switch_event_get_header_nil(event, "event-date-local"),
                                                                           (long) switch_epoch_time_now(NULL),
@@ -1622,11 +1649,21 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
                {
                        char *err;
                        switch_cache_db_test_reactive(dbh, "select call_uuid, read_bit_rate from channels", "DROP TABLE channels", create_channels_sql);
-                       switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql);
+                       if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
+                               switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql);
+                       } else {
+                               char *tmp = switch_string_replace(create_calls_sql, "function", "call_function");
+                               switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", tmp);
+                               free(tmp);
+                       }
                        switch_cache_db_test_reactive(dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql);
                        switch_cache_db_test_reactive(dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql);
 
-                       switch_cache_db_execute_sql(dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err);
+                       if (runtime.odbc_dbtype == DBTYPE_DEFAULT) {
+                               switch_cache_db_execute_sql(dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err);
+                       } else {
+                               switch_cache_db_execute_sql(dbh, "delete from channels where hostname='';delete from channels where hostname='';", &err);
+                       }
 
                        if (err) {
                                runtime.odbc_dsn = NULL;
index c853e14c4c449bb2c012b14d8569c936e834adc9..36c3c996e878916afbbbdcc15b28d4a79a7c329b 100644 (file)
@@ -629,6 +629,32 @@ SWITCH_DECLARE(switch_bool_t) switch_odbc_available(void)
 #endif
 }
 
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLSetAutoCommitAttr(switch_odbc_handle_t *handle, switch_bool_t on)
+{
+#ifdef SWITCH_HAVE_ODBC
+       if (on) {
+               return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_ON, 0 );
+       } else {
+               return SQLSetConnectAttr(handle->con, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER *) SQL_AUTOCOMMIT_OFF, 0 );
+       }
+#else
+       return SWITCH_FALSE;
+#endif
+}
+
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_SQLEndTran(switch_odbc_handle_t *handle, switch_bool_t commit)
+{
+#ifdef SWITCH_HAVE_ODBC
+       if (commit) {
+               return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_COMMIT);
+       } else {
+               return SQLEndTran(SQL_HANDLE_DBC, handle->con, SQL_ROLLBACK);
+       }
+#else
+       return SWITCH_FALSE;
+#endif
+}
+
 
 /* For Emacs:
  * Local Variables: