浏览代码

modules_k/presence: Fixed various issues with the notifier process found during soak testing

Peter Dunkley 13 年之前
父节点
当前提交
0d6e14b1d6
共有 4 个文件被更改,包括 224 次插入154 次删除
  1. 155 133
      modules_k/presence/notify.c
  2. 44 13
      modules_k/presence/presentity.c
  3. 5 3
      modules_k/presence/publish.c
  4. 20 5
      modules_k/presence/subscribe.c

+ 155 - 133
modules_k/presence/notify.c

@@ -2000,7 +2000,7 @@ static int unset_watchers_updated_winfo(str *pres_uri)
 	db_op_t query_ops[2];
 	db1_res_t *result = NULL;
 	int n_query_cols = 0;
-	int ncols, ret = -1;
+	int ret = -1;
 	str winfo = str_init("presence.winfo");
 
 	/* If this is the only presence.winfo dialog awaiting
@@ -2051,10 +2051,8 @@ static int unset_watchers_updated_winfo(str *pres_uri)
 		LM_ERR("bad result\n");
 		goto error;
 	}
-	else
-		ncols = result->n;
 
-	if (ncols <= 1)
+	if (RES_ROW_N(result) <= 0)
 	{
 		query_ops[0] = OP_EQ;
 		query_ops[1] = OP_NEQ;
@@ -2067,7 +2065,10 @@ static int unset_watchers_updated_winfo(str *pres_uri)
 			goto error;
 		}
 
-		ret = 1;
+		if (pa_dbf.affected_rows)
+			ret = pa_dbf.affected_rows(pa_db);
+		else
+			ret = 0;
 	}
 	else
 		ret = 0;
@@ -2077,62 +2078,7 @@ error:
 	return ret;
 }
 
-static int winfo_dialog_pending(str *pres_uri)
-{
-	db_key_t query_cols[3], result_cols[1];
-	db_val_t query_vals[3];
-	db1_res_t *result = NULL;
-	int n_query_cols = 0, ret = -1;
-	str winfo = str_init("presence.winfo");
-
-	query_cols[n_query_cols] = &str_presentity_uri_col;
-	query_vals[n_query_cols].type = DB1_STR;
-	query_vals[n_query_cols].nul = 0;
-	query_vals[n_query_cols].val.str_val.s = pres_uri->s;
-	query_vals[n_query_cols].val.str_val.len = pres_uri->len;
-	n_query_cols++;
-
-	query_cols[n_query_cols] = &str_event_col;
-	query_vals[n_query_cols].type = DB1_STR;
-	query_vals[n_query_cols].nul = 0;
-	query_vals[n_query_cols].val.str_val = winfo;
-	n_query_cols++;
-
-	query_cols[n_query_cols] = &str_updated_col;
-	query_vals[n_query_cols].type = DB1_INT;
-	query_vals[n_query_cols].nul = 0;
-	query_vals[n_query_cols].val.int_val = UPDATED_TYPE;
-	n_query_cols++;
-
-	result_cols[0] = &str_id_col;
-
-	if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
-	{
-		LM_ERR("use table failed\n");
-		goto error;
-	}
-
-	if (pa_dbf.query(pa_db, query_cols, 0, query_vals,
-			 result_cols, n_query_cols, 1, 0, &result) < 0)
-	{
-		LM_ERR("in sql query\n");
-		goto error;
-	}
-
-	if (result == NULL)
-	{
-		LM_ERR("bad result\n");
-		goto error;
-	}
-	else
-		ret = result->n;
-
-error:
-	if (result) pa_dbf.free_result(pa_db, result);
-	return ret;
-}
-
-static int watchers_awaiting_update(str *pres_uri, pres_ev_t *event)
+static int dialogs_awaiting_update(str *pres_uri, str event)
 {
 	db_key_t query_cols[3], result_cols[1];
 	db_val_t query_vals[3];
@@ -2152,7 +2098,7 @@ static int watchers_awaiting_update(str *pres_uri, pres_ev_t *event)
 	query_cols[n_query_cols] = &str_event_col;
 	query_vals[n_query_cols].type = DB1_STR;
 	query_vals[n_query_cols].nul = 0;
-	query_vals[n_query_cols].val.str_val = event->name;
+	query_vals[n_query_cols].val.str_val = event;
 	query_ops[n_query_cols] = OP_EQ;
 	n_query_cols++;
 
@@ -2184,7 +2130,7 @@ static int watchers_awaiting_update(str *pres_uri, pres_ev_t *event)
 		goto error;
 	}
 	else
-		ret = result->n;
+		ret = RES_ROW_N(result);
 
 error:
 	if (result) pa_dbf.free_result(pa_db, result);
@@ -2199,7 +2145,7 @@ int set_wipeer_subs_updated(str *pres_uri, pres_ev_t *event, int full)
 	db1_res_t *result = NULL;
 	int n_query_cols = 0, n_result_cols = 0, n_update_cols = 0;
 	int callid_col, from_tag_col, to_tag_col;
-	int i, ret = -1;
+	int i, ret = -1, count;
 	str callid, from_tag, to_tag;
 
 	query_cols[n_query_cols] = &str_presentity_uri_col;
@@ -2238,13 +2184,14 @@ int set_wipeer_subs_updated(str *pres_uri, pres_ev_t *event, int full)
 		goto error;
 	}
 
-	if (result->n <= 0)
+	if (RES_ROW_N(result) <= 0)
 	{
 		ret = 0;
 		goto done;
 	}
 
 	rows = RES_ROWS(result);
+	count = RES_ROW_N(result);
 	for (i = 0; i < RES_ROW_N(result); i++)
 	{
 		values = ROW_VALUES(&rows[i]);
@@ -2297,9 +2244,12 @@ int set_wipeer_subs_updated(str *pres_uri, pres_ev_t *event, int full)
 			LM_ERR("in sql query\n");
 			goto error;
 		}
+
+		if (pa_dbf.affected_rows)
+			if (pa_dbf.affected_rows(pa_db) == 0) count--;
 	}
 
-	ret = 1;
+	ret = count; 
 
 done:
 error:
@@ -2351,7 +2301,10 @@ int set_updated(subs_t *sub)
 		return -1;
 	}
 
-	return 0;
+	if (pa_dbf.affected_rows)
+		return pa_dbf.affected_rows(pa_db);
+	else
+		return 0;
 }
 
 static watcher_t *build_watchers_list(subs_t *sub)
@@ -2415,7 +2368,7 @@ static watcher_t *build_watchers_list(subs_t *sub)
 		goto error;
 	}
 
-	if (result->n <= 0)
+	if (RES_ROW_N(result) <= 0)
 		goto done;
 
 	rows = RES_ROWS(result);
@@ -2445,6 +2398,43 @@ error:
 	return NULL;
 }
 
+static int cleanup_missing_dialog(subs_t *sub)
+{
+	int ret = -1, num_other_watchers = 0;
+
+	if (sub->event->type & WINFO_TYPE)
+	{
+		if (unset_watchers_updated_winfo(&sub->pres_uri) < 0)
+		{
+			LM_ERR("resetting updated_winfo flags\n");
+			goto error;
+		}
+	}
+	else if (sub->event->type & PUBL_TYPE)
+	{
+		if ((num_other_watchers = dialogs_awaiting_update(
+					&sub->pres_uri, sub->event->name)) < 0)
+		{
+			LM_ERR("checking watchers\n");
+			goto error;
+		}
+		else if (num_other_watchers == 0)
+		{
+			if (delete_offline_presentities(&sub->pres_uri,
+							sub->event) < 0)
+			{
+				LM_ERR("deleting presentity\n");
+				goto error;
+			}
+		}
+	}
+
+	ret = 0;
+
+error:
+	return ret;
+}
+
 static int notifier_notify(subs_t *sub, int *updated)
 {
 	str *nbody = NULL;
@@ -2453,50 +2443,71 @@ static int notifier_notify(subs_t *sub, int *updated)
 
 	*updated = 0;
 
-	if (sub->expires == 0) /* Terminating dialog NOTIFY */
+	/* Terminating dialog NOTIFY */
+	if (sub->expires == 0 || sub->status == TERMINATED_STATUS)
 	{
 		sub->status = TERMINATED_STATUS;
 
 		if (sub->event->type & WINFO_TYPE)
 		{
-			sub->updated = NO_UPDATE_TYPE;
-
 			if (unset_watchers_updated_winfo(&sub->pres_uri) < 0)
 			{
-				LM_ERR("resetting updated_winfo flags\n");
-				goto error;
+				/* Make sure this gets tried again next time */
+				LM_WARN("resetting updated_winfo flags\n");
+				*updated = 1;
+				ret = 0;
+				goto done;
 			}
 		}
 		else
 		{
+			str winfo = str_init("presence.winfo");
+			int num_other_watchers, num_winfos;
+
 			if (sub->event->type & PUBL_TYPE)
 			{
-				int tmp = watchers_awaiting_update(&sub->pres_uri,
-									sub->event);
-				if (tmp < 0)
+				if ((num_other_watchers = dialogs_awaiting_update(
+						&sub->pres_uri, sub->event->name)) < 0)
 				{
 					LM_ERR("checking watchers\n");
 					goto error;
 				}
-				else if (tmp == 0)
+				else if (num_other_watchers == 0)
 					attempt_delete_presentities = 1;
 			}
 
-			if (sub->updated_winfo == UPDATED_TYPE
-				&& winfo_dialog_pending(&sub->pres_uri) > 0)
+			if (sub->event->wipeer)
 			{
+				if ((num_winfos = dialogs_awaiting_update(
+							&sub->pres_uri,
+							winfo)) < 0)
+				{
+					LM_ERR("checking winfos\n");
+					goto error;
+				}
+
+				if (sub->updated_winfo == UPDATED_TYPE && num_winfos > 0)
+				{
 					*updated = 1;
 					ret = 0;
 					goto done;
+				}
 			}
 		}
 	}
 	else /* Non-terminating dialog */
 	{
-		sub->updated = NO_UPDATE_TYPE;
-
 		if (sub->event->type & WINFO_TYPE) /* presence.winfo dialog */
 		{
+			if (unset_watchers_updated_winfo(&sub->pres_uri) < 0)
+			{
+				/* Make sure this gets tried again next time */
+				LM_WARN("resetting updated_winfo flags\n");
+				*updated = 1;
+				ret = 0;
+				goto done;
+			}
+
 			if (sub->updated_winfo == NO_UPDATE_TYPE)
 			{
 				/* Partial notify if
@@ -2527,27 +2538,21 @@ static int notifier_notify(subs_t *sub, int *updated)
 					goto error;
 				}
 
-				if (unset_watchers_updated_winfo(
-							&sub->pres_uri) < 0)
-				{
-					LM_ERR("resetting updated_winfo "
-					       "flags\n");
-					goto error;
-				}
 			}
 			else	/* Full presence.winfo NOTIFY */
 				sub->updated_winfo = NO_UPDATE_TYPE;
 		}
 		else if (sub->event->type & PUBL_TYPE)
 		{
-			int tmp = watchers_awaiting_update(&sub->pres_uri,
-								sub->event);
-			if (tmp < 0)
+			int num_other_watchers;
+
+			if ((num_other_watchers = dialogs_awaiting_update(
+					&sub->pres_uri, sub->event->name)) < 0)
 			{
 				LM_ERR("checking watchers\n");
 				goto error;
 			}
-			else if (tmp == 0)
+			else if (num_other_watchers == 0)
 				attempt_delete_presentities = 1;
 		}
 		else if (!send_fast_notify)
@@ -2563,6 +2568,8 @@ static int notifier_notify(subs_t *sub, int *updated)
 		goto error;
 	}
 
+	ret = 1;
+
 done:
 	if (attempt_delete_presentities)
 	{
@@ -2573,8 +2580,6 @@ done:
 		}
 	}
 
-	ret = 1;
-
 error:
 	free_notify_body(nbody, sub->event);
 	free_watcher_list(watchers);
@@ -2584,7 +2589,7 @@ error:
 
 int process_dialogs(int round, int presence_winfo)
 {
-	db_key_t query_cols[3], result_cols[20], update_cols[4];
+	db_key_t query_cols[3], result_cols[18], update_cols[4];
 	db_val_t query_vals[3], update_vals[4], *values, *dvalues;
 	db_op_t query_ops[2];
 	db_row_t *rows, *drows;
@@ -2596,6 +2601,7 @@ int process_dialogs(int round, int presence_winfo)
 	int rroute_col, event_id_col, reason_col, event_col, lcseq_col;
 	int rcseq_col, status_col, version_col, updated_winfo_col, expires_col;
 	int i, notify_sent = 0, cached_updated_winfo, ret = -1;
+	int end_transaction = 0;
 	subs_t sub;
 	str ev_sname, winfo = str_init("presence.winfo");
 	event_t parsed_event;
@@ -2619,9 +2625,11 @@ int process_dialogs(int round, int presence_winfo)
 	query_ops[n_query_cols] = presence_winfo ? OP_EQ : OP_NEQ;
 	n_query_cols++;
 
+	result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
 	result_cols[callid_col = n_result_cols++] = &str_callid_col;
 	result_cols[to_tag_col = n_result_cols++] = &str_to_tag_col;
 	result_cols[from_tag_col = n_result_cols++] = &str_from_tag_col;
+	result_cols[event_col = n_result_cols++] = &str_event_col;
 	
 	update_cols[n_update_cols] = &str_updated_col;
 	update_vals[n_update_cols].type = DB1_INT;
@@ -2687,9 +2695,17 @@ int process_dialogs(int round, int presence_winfo)
 		memset(&sub, 0, sizeof(subs_t));
 		values = ROW_VALUES(&rows[i]);
 
+		EXTRACT_STRING(sub.pres_uri, VAL_STRING(&values[pres_uri_col]));
 		EXTRACT_STRING(sub.callid, VAL_STRING(&values[callid_col]));
 		EXTRACT_STRING(sub.to_tag, VAL_STRING(&values[to_tag_col]));
 		EXTRACT_STRING(sub.from_tag, VAL_STRING(&values[from_tag_col]));
+		EXTRACT_STRING(ev_sname, VAL_STRING(&values[event_col]));
+		sub.event = contains_event(&ev_sname, &parsed_event);
+		if (sub.event == NULL)
+		{
+			LM_ERR("event not found and set to NULL\n");
+			goto delete_dialog;
+		}
 
 		query_cols[n_query_cols] = &str_callid_col;
 		query_vals[n_query_cols].type = DB1_STR;
@@ -2709,7 +2725,6 @@ int process_dialogs(int round, int presence_winfo)
 		query_vals[n_query_cols].val.str_val = sub.from_tag;
 		n_query_cols++;
 
-		result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
 		result_cols[tuser_col = n_result_cols++] = &str_to_user_col;
 		result_cols[tdomain_col = n_result_cols++] = &str_to_domain_col;
 		result_cols[fuser_col = n_result_cols++] = &str_from_user_col;
@@ -2722,7 +2737,6 @@ int process_dialogs(int round, int presence_winfo)
 		result_cols[rroute_col = n_result_cols++] = &str_record_route_col;
 		result_cols[event_id_col = n_result_cols++] = &str_event_id_col;
 		result_cols[reason_col = n_result_cols++] = &str_reason_col;
-		result_cols[event_col = n_result_cols++] = &str_event_col;
 		result_cols[lcseq_col = n_result_cols++] = &str_local_cseq_col;
 		result_cols[rcseq_col = n_result_cols++] = &str_remote_cseq_col;
 		result_cols[status_col = n_result_cols++] = &str_status_col;
@@ -2738,6 +2752,7 @@ int process_dialogs(int round, int presence_winfo)
 				goto error;
 			}
 		}
+		end_transaction = 1;
 
 		if (pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols,
 				 n_query_cols, n_result_cols, 0, &dialog) < 0)
@@ -2745,11 +2760,21 @@ int process_dialogs(int round, int presence_winfo)
 			LM_ERR("in sql query\n");
 			goto error;
 		}
-		if (dialog == NULL || dialog->n <= 0)
+
+		if (dialog == NULL)
 		{
-			LM_ERR("no records found\n");
+			LM_ERR("bad result\n");
 			goto error;
 		}
+
+		if (dialog->n <= 0)
+		{
+			LM_WARN("record not found\n");
+			if (cleanup_missing_dialog(&sub) < 0)
+				LM_ERR("cleaning up after missing record\n");
+			goto next_dialog;
+		}
+
 		if (dialog->n > 1)
 		{
 			LM_ERR("multiple records found\n");
@@ -2759,7 +2784,6 @@ int process_dialogs(int round, int presence_winfo)
 		drows = RES_ROWS(dialog);
 		dvalues = ROW_VALUES(drows);
 
-		EXTRACT_STRING(sub.pres_uri, VAL_STRING(&dvalues[pres_uri_col]));
 		EXTRACT_STRING(sub.to_user, VAL_STRING(&dvalues[tuser_col]));
 		EXTRACT_STRING(sub.to_domain, VAL_STRING(&dvalues[tdomain_col]));
 		EXTRACT_STRING(sub.from_user, VAL_STRING(&dvalues[fuser_col]));
@@ -2772,13 +2796,6 @@ int process_dialogs(int round, int presence_winfo)
 		EXTRACT_STRING(sub.record_route, VAL_STRING(&dvalues[rroute_col]));
 		EXTRACT_STRING(sub.event_id, VAL_STRING(&dvalues[event_id_col]));
 		EXTRACT_STRING(sub.reason, VAL_STRING(&dvalues[reason_col]));
-		EXTRACT_STRING(ev_sname, VAL_STRING(&dvalues[event_col]));
-		sub.event = contains_event(&ev_sname, &parsed_event);
-		if (sub.event == NULL)
-		{
-			LM_ERR("event not found and set to NULL\n");
-			goto delete_dialog;
-		}
 
 		sub.local_cseq = VAL_INT(&dvalues[lcseq_col]) + 1;
 		sub.remote_cseq = VAL_INT(&dvalues[rcseq_col]);
@@ -2800,7 +2817,21 @@ int process_dialogs(int round, int presence_winfo)
 		{
 			LM_ERR("sending NOTIFY request\n");
 
-			/* On send error remove the dialog and continue */
+			if (pa_dbf.abort_transaction)
+			{
+				if (pa_dbf.abort_transaction(pa_db) < 0)
+				{
+					LM_ERR("in abort_transaction\n");
+					goto error;
+				}
+			}
+			end_transaction = 0;
+
+			if (cleanup_missing_dialog(&sub) < 0)
+				LM_ERR("cleaning up after error sending NOTIFY"
+					"request\n");
+	
+			/* remove the dialog and continue */
 			goto delete_dialog;
 		}
 
@@ -2810,17 +2841,7 @@ int process_dialogs(int round, int presence_winfo)
 			goto error;
 		}
 
-		if ((sub.expires == 0 || sub.status == TERMINATED_STATUS)
-		    && notify_sent)
-		{
-			if (pa_dbf.delete(pa_db, query_cols, 0, query_vals,
-						n_query_cols) < 0)
-			{	
-				LM_ERR("in sql delete");
-				goto error;
-			}
-		}
-		else
+		if (sub.expires > 0 && sub.status != TERMINATED_STATUS)
 		{
 			if (sub.updated_winfo != cached_updated_winfo)
 			{
@@ -2870,26 +2891,27 @@ int process_dialogs(int round, int presence_winfo)
 					goto error;
 				}
 			}
-		}
-
-		goto next_dialog;
 
-delete_dialog:
-		if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
-		{
-			LM_ERR("use table failed\n");
-			goto error;
 		}
+		else if (notify_sent)
+		{
+delete_dialog:
+			if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
+			{
+				LM_ERR("use table failed\n");
+				goto error;
+			}
 
-		if (pa_dbf.delete(pa_db, query_cols, 0, query_vals,
-					n_query_cols) < 0)
-		{	
-			LM_ERR("in sql delete");
-			goto error;
+			if (pa_dbf.delete(pa_db, query_cols, 0, query_vals,
+						n_query_cols) < 0)
+			{	
+				LM_ERR("in sql delete");
+				goto error;
+			}
 		}
 
 next_dialog:
-		if (pa_dbf.end_transaction)
+		if (pa_dbf.end_transaction && end_transaction)
 		{
 			if (pa_dbf.end_transaction(pa_db) < 0)
 			{

+ 44 - 13
modules_k/presence/presentity.c

@@ -1118,13 +1118,13 @@ error:
 
 int mark_presentity_for_delete(presentity_t *pres)
 {
-	db_key_t query_cols[4], result_cols[1], update_cols[2];
-	db_val_t query_vals[4], update_vals[2], *value;
+	db_key_t query_cols[4], result_cols[1], update_cols[3];
+	db_val_t query_vals[4], update_vals[3], *value;
 	db_row_t *row;
 	db1_res_t *result = NULL;
 	int n_query_cols = 0, n_update_cols = 0;
 	int ret = -1;
-	str *cur_body, *new_body = NULL;
+	str *cur_body = NULL, *new_body = NULL;
 
 	if (pres->event->agg_nbody == NULL)
 	{
@@ -1134,8 +1134,6 @@ int mark_presentity_for_delete(presentity_t *pres)
 			LM_ERR("deleting presentity\n");
 			goto error;
 		}
-
-		ret = 0;
 		goto done;
 	}
 
@@ -1184,10 +1182,28 @@ int mark_presentity_for_delete(presentity_t *pres)
 		goto error;
 	}
 
-	if (RES_ROW_N(result) != 1)
+	if (RES_ROW_N(result) <= 0)
+	{
+		/* Can happen when the timer and notifier processes clash */
+		LM_INFO("Found 0 presentities - expected 1\n");
+		goto done;
+	}
+
+	if (RES_ROW_N(result) > 1)
 	{
+		/* More that one is prevented by DB constraint  - but handle
+ 		   it anyway */
 		LM_ERR("Found %d presentities - expected 1\n", RES_ROW_N(result));
-		goto error;
+
+		if (delete_presentity(pres) < 0)
+		{
+			LM_ERR("deleting presentity\n");
+			goto error;
+		}
+
+		/* Want the calling function to continue properly so do not
+		   return an error */
+		goto done;
 	}
 
 	row = RES_ROWS(result);
@@ -1213,6 +1229,12 @@ int mark_presentity_for_delete(presentity_t *pres)
 	update_vals[n_update_cols].val.str_val = str_offline_etag_val;
 	n_update_cols++;
 
+	update_cols[n_update_cols] = &str_expires_col;
+	update_vals[n_update_cols].type = DB1_INT;
+	update_vals[n_update_cols].nul = 0;
+	update_vals[n_update_cols].val.int_val = (int)time(NULL);
+	n_update_cols++;
+
 	update_cols[n_update_cols] = &str_body_col;
 	update_vals[n_update_cols].type = DB1_STR;
 	update_vals[n_update_cols].nul = 0;
@@ -1220,15 +1242,19 @@ int mark_presentity_for_delete(presentity_t *pres)
 	update_vals[n_update_cols].val.str_val.len = new_body->len;
 	n_update_cols++;
 
-	if(pa_dbf.update(pa_db, query_cols, 0, query_vals, update_cols,
+	if (pa_dbf.update(pa_db, query_cols, 0, query_vals, update_cols,
 			 update_vals, n_query_cols, n_update_cols) < 0)
 	{
 		LM_ERR("unsuccessful sql update operation");
 		goto error;
 	}
 
-	ret = 1;
+	if (pa_dbf.affected_rows)
+		ret = pa_dbf.affected_rows(pa_db);
+	else
 done:
+		ret = 0;
+
 error:
 	free_notify_body(new_body, pres->event);
 	if (cur_body) pkg_free(cur_body);
@@ -1241,7 +1267,6 @@ int delete_presentity(presentity_t *pres)
 	db_key_t query_cols[4];
 	db_val_t query_vals[4];
 	int n_query_cols = 0;
-	int ret = -1;
 
 	if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
 	{
@@ -1279,10 +1304,13 @@ int delete_presentity(presentity_t *pres)
 		goto error;
 	}
 
-	ret = 0;
+	if (pa_dbf.affected_rows)
+		return pa_dbf.affected_rows(pa_db);
+	else
+		return 0;
 
 error:
-	return ret;
+	return -1;
 }
 
 int delete_offline_presentities(str *pres_uri, pres_ev_t *event)
@@ -1334,7 +1362,10 @@ int delete_offline_presentities(str *pres_uri, pres_ev_t *event)
 		goto error;
 	}
 
-	return 0;
+	if (pa_dbf.affected_rows)
+		return pa_dbf.affected_rows(pa_db);
+	else
+		return 0;
 
 error:
 	return -1;

+ 5 - 3
modules_k/presence/publish.c

@@ -246,8 +246,6 @@ void msg_presentity_clean(unsigned int ticks,void *param)
 		}
 		else
 		{
-			rules_doc= NULL;
-		
 			if(p[i].p->event->get_rules_doc && 
 				p[i].p->event->get_rules_doc(&p[i].p->user,
 								&p[i].p->domain,
@@ -267,13 +265,17 @@ void msg_presentity_clean(unsigned int ticks,void *param)
 				if(rules_doc->s)
 					pkg_free(rules_doc->s);
 				pkg_free(rules_doc);
+				rules_doc= NULL;
+	
 			}
 		}
-		rules_doc= NULL;
 		pkg_free(p[i].p);
+		p[i].p = NULL;
 		pkg_free(p[i].uri.s);
+		p[i].uri.s = NULL;
 	}
 	pkg_free(p);
+	p = NULL;
 
 	if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
 	{

+ 20 - 5
modules_k/presence/subscribe.c

@@ -467,6 +467,8 @@ void delete_subs(str* pres_uri, str* ev_name, str* to_tag,
 int update_subscription_notifier(struct sip_msg* msg, subs_t* subs,
 		int to_tag_gen, int* sent_reply)
 {
+	int num_peers = 0;
+
 	*sent_reply= 0;
 
 	/* Set the notifier/update fields for the subscription */
@@ -477,14 +479,22 @@ int update_subscription_notifier(struct sip_msg* msg, subs_t* subs,
 		subs->updated_winfo = UPDATED_TYPE;
 	else if (subs->event->wipeer)
 	{
-		if (set_wipeer_subs_updated(&subs->pres_uri,
+		if ((num_peers = set_wipeer_subs_updated(&subs->pres_uri,
 						subs->event->wipeer,
-						subs->expires == 0) < 0)
+						subs->expires == 0)) < 0)
 		{
 			LM_ERR("failed to update database record(s)\n");
 			goto error;
 		}
-		subs->updated_winfo = UPDATED_TYPE;
+
+		if (num_peers > 0)
+			subs->updated_winfo = UPDATED_TYPE;
+	}
+	if (subs->expires == 0)
+	{
+		subs->status = TERMINATED_STATUS;
+		subs->reason.s = "timeout";
+		subs->reason.len = 7;
 	}
 
 	printf_subs(subs);
@@ -510,7 +520,8 @@ int update_subscription_notifier(struct sip_msg* msg, subs_t* subs,
 	if(send_2XX_reply(msg, subs->event->type & PUBL_TYPE ? 202 : 200,
 				subs->expires, &subs->local_contact) < 0)
 	{
-		LM_ERR("sending 202 OK\n");
+		LM_ERR("sending %d response\n",
+			subs->event->type & PUBL_TYPE ? 202 : 200);
 		goto error;
 	}
 	*sent_reply= 1;
@@ -1613,7 +1624,11 @@ void update_db_subs_timer_notifier(void)
 		goto error;
 	}
 
-	if(result == NULL) goto error;
+	if(result == NULL)
+	{
+		LM_ERR("bad result\n");
+		goto error;
+	}
 
 	do {
 		rows = RES_ROWS(result);