Revision
17086
Author
rupa
Date
2010-03-24 11:17:58 -0500 (Wed, 24 Mar 2010)

Log Message

merge branch up to 17085

Modified Paths

Diff

Modified: freeswitch/branches/rupa_limit/conf/autoload_configs/nibblebill.conf.xml (17085 => 17086)


--- freeswitch/branches/rupa_limit/conf/autoload_configs/nibblebill.conf.xml	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/conf/autoload_configs/nibblebill.conf.xml	2010-03-24 16:17:58 UTC (rev 17086)
@@ -16,7 +16,21 @@
     <!-- The column name for the unique ID identifying the account -->
     <param name="db_column_account" value="id"/>
 
+    <!-- Custom SQL for loading current balance - overrides column names
+         channel vars are interpreted.
+         field nibble_balance is used for balance info
 
+    <param name="custom_sql_lookup" value="SELECT cash AS nibble_balance FROM accounts WHERE account_code='${nibble_account}'"/>
+    -->
+
+    <!-- Custom SQL for loading current balance - overrides column names
+         channel vars are interpreted.
+         nibble_increment is the amount to update
+
+    <param name="custom_sql_save" value="UPDATE accounts SET cash=cash-${nibble_increment} WHERE account_code='${nibble_account}'"/>
+    -->
+
+
     <!-- Default heartbeat interval. Set to 'off' for no heartbeat (i.e. bill only at end of call) -->
     <param name="global_heartbeat" value="60"/>
 

Modified: freeswitch/branches/rupa_limit/src/include/switch_core.h (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/include/switch_core.h	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/include/switch_core.h	2010-03-24 16:17:58 UTC (rev 17086)
@@ -1202,6 +1202,14 @@
 SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_mutex_t *mutex);
 
 /*! 
+  \brief Delete data from a hash based on callback function
+  \param hash the hash to delete from
+  \param callback the function to call which returns SWITCH_TRUE to delete, SWITCH_FALSE to preserve
+  \return SWITCH_STATUS_SUCCESS if any data is deleted
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(_In_ switch_hash_t *hash, _In_ switch_hash_delete_callback_t callback, _In_opt_ void *pData);
+
+/*! 
   \brief Retrieve data from a given hash
   \param hash the hash to retrieve from
   \param key the key to retrieve

Modified: freeswitch/branches/rupa_limit/src/include/switch_types.h (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/include/switch_types.h	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/include/switch_types.h	2010-03-24 16:17:58 UTC (rev 17086)
@@ -1562,6 +1562,8 @@
 typedef switch_caller_extension_t *(*switch_dialplan_hunt_function_t) (switch_core_session_t *, void *, switch_caller_profile_t *);
 #define SWITCH_STANDARD_DIALPLAN(name) static switch_caller_extension_t *name (switch_core_session_t *session, void *arg, switch_caller_profile_t *caller_profile)
 
+typedef switch_bool_t (*switch_hash_delete_callback_t) (_In_ const void *key, _In_ const void *val, _In_opt_ void *pData);
+#define SWITCH_HASH_DELETE_FUNC(name) static switch_bool_t name (const void *key, const void *val, void *pData)
 
 typedef struct switch_scheduler_task switch_scheduler_task_t;
 

Modified: freeswitch/branches/rupa_limit/src/mod/applications/mod_dptools/mod_dptools.c (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/mod/applications/mod_dptools/mod_dptools.c	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/mod/applications/mod_dptools/mod_dptools.c	2010-03-24 16:17:58 UTC (rev 17086)
@@ -3014,7 +3014,7 @@
 			max = -1;
 		} else {
 			char *szinterval = NULL;
-			if ((szinterval = strchr(argv[2], '/'))) {
+			if ((szinterval = strchr(argv[3], '/'))) {
 				*szinterval++ = '\0';
 				interval = atoi(szinterval);
 			}

Modified: freeswitch/branches/rupa_limit/src/mod/applications/mod_hash/mod_hash.c (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/mod/applications/mod_hash/mod_hash.c	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/mod/applications/mod_hash/mod_hash.c	2010-03-24 16:17:58 UTC (rev 17086)
@@ -91,6 +91,7 @@
 	/* Check if that realm+resource has ever been checked */
 	if (!(item = (limit_hash_item_t *) switch_core_hash_find(globals.limit_hash, hashkey))) {
 		/* No, create an empty structure and add it, then continue like as if it existed */
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Creating new limit structure: key: %s\n", hashkey);
 		item = (limit_hash_item_t *) malloc(sizeof(limit_hash_item_t));
 		switch_assert(item);
 		memset(item, 0, sizeof(limit_hash_item_t));
@@ -105,7 +106,7 @@
 		 */
 		increment = !switch_core_hash_find(pvt->hash, hashkey);
 	} else {
-		/* This is the first limit check on this channel, create a hashtable, set our prviate data and add a state handler */
+		/* This is the first limit check on this channel, create a hashtable, set our prviate data */
 		pvt = (limit_hash_private_t *) switch_core_session_alloc(session, sizeof(limit_hash_private_t));
 		memset(pvt, 0, sizeof(limit_hash_private_t));
 		switch_core_hash_init(&pvt->hash, switch_core_session_get_pool(session));
@@ -116,6 +117,8 @@
 		if (item->last_check <= (now - interval)) {
 			item->rate_usage = 1;
 			item->last_check = now;
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Usage for %s reset to 1\n",
+							  hashkey);
 		} else {
 			/* Always increment rate when its checked as it doesnt depend on the channel */
 			item->rate_usage++;
@@ -197,7 +200,7 @@
 			item->total_usage--;
 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d\n", (const char *) key, item->total_usage);
 
-			if (item->total_usage == 0) {
+			if (item->total_usage == 0 && item->rate_usage == 0) {
 				/* Noone is using this item anymore */
 				switch_core_hash_delete(globals.limit_hash, (const char *) key);
 				free(item);
@@ -214,7 +217,7 @@
 
 			switch_core_hash_delete(pvt->hash, hashkey);
 
-			if (item->total_usage == 0) {
+			if (item->total_usage == 0 && item->rate_usage == 0) {
 				/* Noone is using this item anymore */
 				switch_core_hash_delete(globals.limit_hash, (const char *) hashkey);
 				free(item);

Modified: freeswitch/branches/rupa_limit/src/mod/applications/mod_nibblebill/mod_nibblebill.c (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/mod/applications/mod_nibblebill/mod_nibblebill.c	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/mod/applications/mod_nibblebill/mod_nibblebill.c	2010-03-24 16:17:58 UTC (rev 17086)
@@ -51,7 +51,7 @@
 #include <switch.h>
 
 /* Defaults */
-static char SQL_LOOKUP[] = "SELECT %s FROM %s WHERE %s='%s'";
+static char SQL_LOOKUP[] = "SELECT %s AS nibble_balance FROM %s WHERE %s='%s'";
 static char SQL_SAVE[] = "UPDATE %s SET %s=%s-%f WHERE %s='%s'";
 
 typedef struct {
@@ -101,6 +101,8 @@
 	char *db_table;
 	char *db_column_cash;
 	char *db_column_account;
+	char *custom_sql_save;
+	char *custom_sql_lookup;
 	switch_odbc_handle_t *master_odbc;
 } globals;
 
@@ -125,16 +127,23 @@
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_table, globals.db_table);
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_column_cash, globals.db_column_cash);
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_db_column_account, globals.db_column_account);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_custom_sql_save, globals.custom_sql_save);
+SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_custom_sql_lookup, globals.custom_sql_lookup);
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_percall_action, globals.percall_action);
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_lowbal_action, globals.lowbal_action);
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_nobal_action, globals.nobal_action);
 
 static int nibblebill_callback(void *pArg, int argc, char **argv, char **columnNames)
 {
+	int i = 0;
 	nibblebill_results_t *cbt = (nibblebill_results_t *) pArg;
 
-	cbt->balance = (float) atof(argv[0]);
-
+	for (i = 0; i < argc; i++) {
+		if (!strcasecmp(columnNames[i], "nibble_balance")) {
+			cbt->balance = (float) atof(argv[0]);
+		}
+	}
+	
 	return 0;
 }
 
@@ -167,6 +176,10 @@
 				set_global_db_column_cash(val);
 			} else if (!strcasecmp(var, "db_column_account")) {
 				set_global_db_column_account(val);
+			} else if (!strcasecmp(var, "custom_sql_save")) {
+				set_global_custom_sql_save(val);
+			} else if (!strcasecmp(var, "custom_sql_lookup")) {
+				set_global_custom_sql_lookup(val);
 			} else if (!strcasecmp(var, "percall_action")) {
 				set_global_percall_action(val);
 			} else if (!strcasecmp(var, "percall_max_amt")) {
@@ -285,17 +298,29 @@
 
 
 /* At this time, billing never succeeds if you don't have a database. */
-static switch_status_t bill_event(float billamount, const char *billaccount)
+static switch_status_t bill_event(float billamount, const char *billaccount, switch_channel_t *channel)
 {
-	char sql[1024] = "";
-	switch_odbc_statement_handle_t stmt;
+	switch_stream_handle_t sql_stream = { 0 };
+	char *sql = NULL;
+	switch_odbc_statement_handle_t stmt = NULL;
+	SWITCH_STANDARD_STREAM(sql_stream);
 
 	if (!switch_odbc_available()) {
-		return SWITCH_STATUS_SUCCESS;
+		goto end;
 	}
 
-	switch_snprintf(sql, 1024, SQL_SAVE, globals.db_table, globals.db_column_cash, globals.db_column_cash, billamount, globals.db_column_account,
-					billaccount);
+	if (globals.custom_sql_save) {
+		if (switch_string_var_check_const(globals.custom_sql_save) || switch_string_has_escaped_data(globals.custom_sql_save)) {
+			switch_channel_set_variable_printf(channel, "nibble_increment", "%f", billamount, SWITCH_FALSE);
+			sql = switch_channel_expand_variables(channel, globals.custom_sql_save);
+		} else {
+			sql = globals.custom_sql_save;
+		}
+	} else {
+		sql_stream.write_function(&sql_stream, SQL_SAVE, globals.db_table, globals.db_column_cash, globals.db_column_cash, billamount, globals.db_column_account,
+						billaccount);
+		sql = sql_stream.data;
+	}
 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing update query\n[%s]\n", sql);
 
 	if (switch_odbc_handle_exec(globals.master_odbc, sql, &stmt, NULL) != SWITCH_ODBC_SUCCESS) {
@@ -306,40 +331,63 @@
 	} else {
 		/* TODO: Failover to a flat/text file if DB is unavailable */
 
-		return SWITCH_STATUS_SUCCESS;
+		goto end;
 	}
 
 	switch_odbc_statement_handle_free(&stmt);
 
+end:
+	if (sql != globals.custom_sql_save) {
+		switch_safe_free(sql);
+	}
 	return SWITCH_STATUS_SUCCESS;
 }
 
 
-static float get_balance(const char *billaccount)
+static float get_balance(const char *billaccount, switch_channel_t *channel)
 {
-	char sql[1024] = "";
+	switch_stream_handle_t sql_stream = { 0 };
+	char *sql = NULL;
 	nibblebill_results_t pdata;
 	float balance = 0.00f;
+	SWITCH_STANDARD_STREAM(sql_stream);
 
 	if (!switch_odbc_available()) {
-		return -1.00f;
+		balance = -1.00f;
+		goto end;
 	}
 
 	memset(&pdata, 0, sizeof(pdata));
-	snprintf(sql, 1024, SQL_LOOKUP, globals.db_column_cash, globals.db_table, globals.db_column_account, billaccount);
 
+	if (globals.custom_sql_lookup) {
+		if (switch_string_var_check_const(globals.custom_sql_lookup) || switch_string_has_escaped_data(globals.custom_sql_lookup)) {
+			sql = switch_channel_expand_variables(channel, globals.custom_sql_lookup);
+		} else {
+			sql = globals.custom_sql_lookup;
+		}
+	} else {
+		sql_stream.write_function(&sql_stream, SQL_LOOKUP, globals.db_column_cash, globals.db_table, globals.db_column_account, billaccount);
+		sql = sql_stream.data;
+	}
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing lookup query\n[%s]\n", sql);
+	
 	if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, nibblebill_callback, &pdata, NULL) != SWITCH_ODBC_SUCCESS) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error running this query: [%s]\n", sql);
 		/* Return -1 for safety */
 
-		return -1.00f;
+		balance = -1.00f;
+		goto end;
 	} else {
 		/* Successfully retrieved! */
 		balance = pdata.balance;
 
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Retrieved current balance for account %s (balance = %f)\n", billaccount, balance);
 	}
-
+	
+end:
+	if (sql != globals.custom_sql_lookup) {
+		switch_safe_free(sql);
+	}
 	return balance;
 }
 
@@ -408,7 +456,7 @@
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not billing %s - call is not in answered state\n", billaccount);
 
 		/* See if this person has enough money left to continue the call */
-		balance = get_balance(billaccount);
+		balance = get_balance(billaccount, channel);
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f\n", balance, nobal_amt);
 		if (balance <= nobal_amt) {
 			/* Not enough money - reroute call to nobal location */
@@ -464,7 +512,7 @@
 						  uuid, nibble_data->total);
 
 		/* DO ODBC BILLING HERE and reset counters if it's successful! */
-		if (bill_event(billamount, billaccount) == SWITCH_STATUS_SUCCESS) {
+		if (bill_event(billamount, billaccount, channel) == SWITCH_STATUS_SUCCESS) {
 			/* Increment total cost */
 			nibble_data->total += billamount;
 
@@ -491,7 +539,7 @@
 		/* don't verify balance and transfer to nobal if we're done with call */
 		if (switch_channel_get_state(channel) != CS_REPORTING && switch_channel_get_state(channel) != CS_HANGUP) {
 			/* See if this person has enough money left to continue the call */
-			balance = get_balance(billaccount);
+			balance = get_balance(billaccount, channel);
 			if (balance <= nobal_amt) {
 				/* Not enough money - reroute call to nobal location */
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
@@ -719,7 +767,7 @@
 	}
 
 	/* Add or remove amount from adjusted billing here. Note, we bill the OPPOSITE */
-	if (bill_event(-amount, billaccount) == SWITCH_STATUS_SUCCESS) {
+	if (bill_event(-amount, billaccount, channel) == SWITCH_STATUS_SUCCESS) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Recorded adjustment to %s for $%f\n", billaccount, amount);
 	} else {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to record adjustment to %s for $%f\n", billaccount, amount);
@@ -846,7 +894,7 @@
 
 	billaccount = switch_channel_get_variable(channel, "nibble_account");
 	if (billaccount) {
-		switch_channel_set_variable_printf(channel, "nibble_current_balance", "%f", get_balance(billaccount));
+		switch_channel_set_variable_printf(channel, "nibble_current_balance", "%f", get_balance(billaccount, channel));
 	}			
 	
 	return SWITCH_STATUS_SUCCESS;

Modified: freeswitch/branches/rupa_limit/src/mod/endpoints/mod_skypopen/alsa/dummy.c (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/mod/endpoints/mod_skypopen/alsa/dummy.c	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/mod/endpoints/mod_skypopen/alsa/dummy.c	2010-03-24 16:17:58 UTC (rev 17086)
@@ -18,7 +18,7 @@
  *
  */
 
-#include <sound/driver.h>		//giova
+//#include <sound/driver.h>		//giova
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
@@ -106,6 +106,7 @@
 	struct snd_pcm_substream *substream;
 	struct snd_dummy_pcm *dpcm;
 	int started;
+	int elapsed;
 };
 static struct giovadpcm giovadpcms[MAX_PCM_SUBSTREAMS];
 
@@ -127,8 +128,8 @@
 
 struct snd_dummy_pcm {
 	struct snd_dummy *dummy;
-	spinlock_t lock;
-	struct timer_list timer;
+	//spinlock_t lock;
+	//struct timer_list timer;
 	unsigned int pcm_buffer_size;
 	unsigned int pcm_period_size;
 	unsigned int pcm_bps;		/* bytes per second */
@@ -171,6 +172,7 @@
 		}
 		if (giovadpcms[i].dpcm == dpcm) {
 			giovadpcms[i].started = 0;
+			giovadpcms[i].elapsed = 0;
 			found = 1;
 		}
 	}
@@ -234,6 +236,7 @@
 	giovatimer.expires = 1 + jiffies;
 	add_timer(&giovatimer);
 
+	spin_lock_bh(&giovalock);
 	for (i = 0; i < giovaindex + 1; i++) {
 
 		if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
@@ -246,18 +249,38 @@
 			printk("giova: timer_func %d %d NULL: continue\n", __LINE__, i);
 			continue;
 		}
-		spin_lock_bh(&dpcm->lock);
-		dpcm->pcm_irq_pos += dpcm->pcm_bps;
-		dpcm->pcm_buf_pos += dpcm->pcm_bps;
+		//spin_lock_bh(&dpcm->lock);
+		dpcm->pcm_irq_pos += dpcm->pcm_bps * 1;
+		dpcm->pcm_buf_pos += dpcm->pcm_bps * 1;
 		dpcm->pcm_buf_pos %= dpcm->pcm_buffer_size * dpcm->pcm_hz;
 		if (dpcm->pcm_irq_pos >= dpcm->pcm_period_size * dpcm->pcm_hz) {
 			dpcm->pcm_irq_pos %= dpcm->pcm_period_size * dpcm->pcm_hz;
-			spin_unlock_bh(&dpcm->lock);
-			snd_pcm_period_elapsed(dpcm->substream);
+			//spin_unlock_bh(&dpcm->lock);
+			//snd_pcm_period_elapsed(dpcm->substream);
+			giovadpcms[i].elapsed = 1;
 		} else {
-			spin_unlock_bh(&dpcm->lock);
+			//spin_unlock_bh(&dpcm->lock);
 		}
 	}
+	spin_unlock_bh(&giovalock);
+	for (i = 0; i < giovaindex + 1; i++) {
+
+		if (i > MAX_PCM_SUBSTREAMS || giovaindex > MAX_PCM_SUBSTREAMS) {
+			printk("giova, %s:%d, i=%d, giovaindex=%d dpcm=%p\n", __FILE__, __LINE__, i, giovaindex, dpcm);
+		}
+		if (giovadpcms[i].started != 1)
+			continue;
+		dpcm = giovadpcms[i].dpcm;
+		if (dpcm == NULL) {
+			printk("giova: timer_func %d %d NULL: continue\n", __LINE__, i);
+			continue;
+		}
+		if (giovadpcms[i].elapsed){
+			snd_pcm_period_elapsed(dpcm->substream);
+			giovadpcms[i].elapsed = 0;
+		}
+	}
+
 }
 
 static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream)
@@ -265,7 +288,8 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_dummy_pcm *dpcm = runtime->private_data;
 
-	return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
+	//return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz);
+	return (dpcm->pcm_buf_pos / dpcm->pcm_hz) / 2;
 }
 
 static struct snd_pcm_hardware snd_card_dummy_playback = {
@@ -277,7 +301,7 @@
 	.channels_min = USE_CHANNELS_MIN,
 	.channels_max = USE_CHANNELS_MAX,
 	.buffer_bytes_max = MAX_BUFFER_SIZE,
-	.period_bytes_min = 64,
+	.period_bytes_min = 256,
 	.period_bytes_max = MAX_PERIOD_SIZE,
 	.periods_min = USE_PERIODS_MIN,
 	.periods_max = USE_PERIODS_MAX,
@@ -293,7 +317,7 @@
 	.channels_min = USE_CHANNELS_MIN,
 	.channels_max = USE_CHANNELS_MAX,
 	.buffer_bytes_max = MAX_BUFFER_SIZE,
-	.period_bytes_min = 64,
+	.period_bytes_min = 256,
 	.period_bytes_max = MAX_PERIOD_SIZE,
 	.periods_min = USE_PERIODS_MIN,
 	.periods_max = USE_PERIODS_MAX,
@@ -313,6 +337,7 @@
 		}
 		if ((giovadpcms[i].dpcm == runtime->private_data)) {
 			giovadpcms[i].started = 0;
+			giovadpcms[i].elapsed = 0;
 		} else {
 		}
 	}
@@ -342,8 +367,8 @@
 		printk("giova, %s:%d, giovaindex=%d NO MEMORY!!!!\n", __FILE__, __LINE__, giovaindex);
 		return dpcm;
 	}
-	init_timer(&dpcm->timer);
-	spin_lock_init(&dpcm->lock);
+	//init_timer(&dpcm->timer);
+	//spin_lock_init(&dpcm->lock);
 	dpcm->substream = substream;
 
 	spin_lock_bh(&giovalock);
@@ -376,6 +401,7 @@
 		if (giovadpcms[i].substream == substream) {
 			giovadpcms[i].dpcm = dpcm;
 			giovadpcms[i].started = 0;
+			giovadpcms[i].elapsed = 0;
 			found = 1;
 			break;
 		}
@@ -630,14 +656,14 @@
 	int idx, err;
 	int dev = devptr->id;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_dummy)); //giova if this gives you problems, comment it out and remove comment from the 4 lines commented below
-	if (card == NULL) //giova if this gives you problems, comment it out and remove comment from the 4 lines commented below
-		return -ENOMEM; //giova if this gives you problems, comment it out and remove comment from the 4 lines commented below
+	//card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct snd_dummy)); //giova if this gives you problems, comment it out and remove comment from the 4 lines commented below
+	//if (card == NULL) //giova if this gives you problems, comment it out and remove comment from the 4 lines commented below
+		//return -ENOMEM; //giova if this gives you problems, comment it out and remove comment from the 4 lines commented below
 
-	//giova err = snd_card_create(index[dev], id[dev], THIS_MODULE,
-	//giova sizeof(struct snd_dummy), &card);
-	//giova if (err < 0)
-	//giova return err;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+	sizeof(struct snd_dummy), &card);
+	if (err < 0)
+	return err;
 
 	dummy = card->private_data;
 	dummy->card = card;
@@ -741,13 +767,14 @@
 			giovadpcms[i].substream = NULL;
 			giovadpcms[i].dpcm = NULL;
 			giovadpcms[i].started = 0;
+			giovadpcms[i].elapsed = 0;
 		}
 		init_timer(&giovatimer);
 		giovatimer.data = (unsigned long) &giovadpcms;
 		giovatimer.function = snd_card_dummy_pcm_timer_function;
 		giovatimer.expires = 1 + jiffies;
 		add_timer(&giovatimer);
-		printk("snd-dummy skypopen driver version: 3, %s:%d working on a machine with %dHZ kernel\n", __FILE__, __LINE__, HZ);
+		printk("snd-dummy skypopen driver version: 5, %s:%d working on a machine with %dHZ kernel\n", __FILE__, __LINE__, HZ);
 		spin_unlock_bh(&giovalock);
 	}
 

Modified: freeswitch/branches/rupa_limit/src/switch_core_hash.c (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/switch_core_hash.c	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/switch_core_hash.c	2010-03-24 16:17:58 UTC (rev 17086)
@@ -117,6 +117,42 @@
 	return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(switch_hash_t *hash, switch_hash_delete_callback_t callback, void *pData) {
+
+	switch_hash_index_t *hi = NULL;
+	switch_event_t *event = NULL;
+	switch_event_header_t *header = NULL;
+	switch_status_t status = SWITCH_STATUS_GENERR;
+	
+	switch_event_create_subclass(&event, SWITCH_EVENT_CLONE, NULL);
+	switch_assert(event);
+	
+	/* iterate through the hash, call callback, if callback returns true, put the key on the list (event)
+	   When done, iterate through the list deleting hash entries
+	 */
+	
+	for (hi = switch_hash_first(NULL, hash); hi; hi = switch_hash_next(hi)) {
+		const void *key;
+		void *val;
+		switch_hash_this(hi, &key, NULL, &val);
+		if (callback(key, val, pData)) {
+			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delete", (const char *) key);
+		}
+	}
+	
+	/* now delete them */
+	for (header = event->headers; header; header = header->next) {
+		if (switch_core_hash_delete(hash, header->value) == SWITCH_STATUS_SUCCESS) {
+			status = SWITCH_STATUS_SUCCESS;
+		}
+	}
+
+	switch_event_destroy(&event);
+	
+	return status;
+}
+
+
 SWITCH_DECLARE(void *) switch_core_hash_find(switch_hash_t *hash, const char *key)
 {
 	return sqlite3HashFind(&hash->table, key, (int) strlen(key) + 1);

Modified: freeswitch/branches/rupa_limit/src/switch_limit.c (17085 => 17086)


--- freeswitch/branches/rupa_limit/src/switch_limit.c	2010-03-24 16:11:24 UTC (rev 17085)
+++ freeswitch/branches/rupa_limit/src/switch_limit.c	2010-03-24 16:17:58 UTC (rev 17086)
@@ -119,6 +119,9 @@
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
 		switch_goto_status(SWITCH_STATUS_GENERR, end);
 	}
+
+	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "incr called: %s_%s max:%d, interval:%d\n",
+					  realm, resource, max, interval);
 	
 	if ((status = limit->incr(session, realm, resource, max, interval)) == SWITCH_STATUS_SUCCESS) {
 		/* race condition? what if another leg is doing the same thing? */