hello, attached is a major rework of the group count function
As a fix for ticket 452 to prevent wrong values in group count
the patch is a backport from changeset 61804 from ast
Kristijan (aka wildzero-cw)
Index: corelib/channel.c
===================================================================
--- corelib/channel.c (revision 5364)
+++ corelib/channel.c (working copy)
@@ -1064,6 +1064,8 @@
/* List Deletion. */
vardata = CW_LIST_REMOVE_HEAD(headp, entries);
cw_var_delete(vardata);
+ /* Drop out of the group counting radar */
+ cw_app_group_discard(chan);
}
/* Destroy the jitterbuffer */
@@ -2902,24 +2904,7 @@
static void clone_variables(struct cw_channel *original, struct cw_channel
*clone)
{
- struct cw_var_t *varptr;
- /* we need to remove all app_groupcount related variables from the
original
- channel before merging in the clone's variables; any groups assigned
to the
- original channel should be released, only those assigned to the clone
- should remain
- */
-
- CW_LIST_TRAVERSE_SAFE_BEGIN(&original->varshead, varptr, entries)
- {
- if (!strncmp(cw_var_name(varptr), GROUP_CATEGORY_PREFIX,
strlen(GROUP_CATEGORY_PREFIX)))
- {
- CW_LIST_REMOVE(&original->varshead, varptr, entries);
- cw_var_delete(varptr);
- }
- }
- CW_LIST_TRAVERSE_SAFE_END;
-
/* Append variables from clone channel into original channel */
/* XXX Is this always correct? We have to in order to keep PROCS
working XXX */
if (CW_LIST_FIRST(&clone->varshead))
@@ -3083,6 +3068,9 @@
/* Copy the FD's */
for (x = 0; x < CW_MAX_FDS; x++)
original->fds[x] = clone->fds[x];
+
+ /* Drop group from original */
+ cw_app_group_discard(original);
clone_variables(original, clone);
CW_LIST_HEAD_INIT_NOLOCK(&clone->varshead);
/* Presense of ADSI capable CPE follows clone */
Index: corelib/app.c
===================================================================
--- corelib/app.c (revision 5364)
+++ corelib/app.c (working copy)
@@ -52,10 +52,13 @@
#include "callweaver/utils.h"
#include "callweaver/lock.h"
#include "callweaver/indications.h"
+#include "callweaver/linkedlists.h"
#define MAX_OTHER_FORMATS 10
+static CW_LIST_HEAD_STATIC(groups, cw_group_info);
+
/*
This function presents a dialtone and reads an extension into 'collect'
which must be a pointer to a **pre-initilized** array of char having a
@@ -1047,61 +1050,75 @@
else
res = -1;
- if (cat)
- snprintf(category, category_max, "%s_%s",
GROUP_CATEGORY_PREFIX, cat);
- else
- cw_copy_string(category, GROUP_CATEGORY_PREFIX, category_max);
+ if (!cw_strlen_zero(cat))
+ cw_copy_string(category, cat, category_max);
return res;
}
int cw_app_group_set_channel(struct cw_channel *chan, char *data)
{
- int res=0;
- char group[80] = "";
- char category[80] = "";
+ int res = 0;
+ char group[80] = "", category[80] = "";
+ struct cw_group_info *gi = NULL;
+ size_t len = 0;
- if (!cw_app_group_split_group(data, group, sizeof(group), category,
sizeof(category))) {
- pbx_builtin_setvar_helper(chan, category, group);
- } else
- res = -1;
+ if (cw_app_group_split_group(data, group, sizeof(group), category,
sizeof(category)))
+ return -1;
+ /* Calculate memory we will need if this is new */
+ len = sizeof(*gi) + strlen(group) + 1;
+ if (!cw_strlen_zero(category))
+ len += strlen(category) + 1;
+
+ CW_LIST_LOCK(&groups);
+ CW_LIST_TRAVERSE(&groups, gi, list) {
+ if (gi->chan == chan && !strcasecmp(gi->group, group) &&
(cw_strlen_zero(category) || (!cw_strlen_zero(gi->category) &&
!strcasecmp(gi->category, category))))
+ break;
+ }
+
+ if (!gi && (gi = calloc(1, len))) {
+ gi->chan = chan;
+ gi->group = (char *) gi + sizeof(*gi);
+ strcpy(gi->group, group);
+ if (!cw_strlen_zero(category)) {
+ gi->category = (char *) gi + sizeof(*gi) +
strlen(group) + 1;
+ strcpy(gi->category, category);
+ }
+ CW_LIST_INSERT_TAIL(&groups, gi, list);
+ } else {
+ res = -1;
+ }
+
+ CW_LIST_UNLOCK(&groups);
+
+
return res;
}
int cw_app_group_get_count(char *group, char *category)
{
- struct cw_channel *chan;
+ struct cw_group_info *gi = NULL;
int count = 0;
- char *test;
- char cat[80];
- char *s;
if (cw_strlen_zero(group))
return 0;
- s = (!cw_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX;
- cw_copy_string(cat, s, sizeof(cat));
-
- chan = NULL;
- while ((chan = cw_channel_walk_locked(chan)) != NULL) {
- test = pbx_builtin_getvar_helper(chan, cat);
- if (test && !strcasecmp(test, group))
- count++;
- cw_mutex_unlock(&chan->lock);
+ CW_LIST_LOCK(&groups);
+ CW_LIST_TRAVERSE(&groups, gi, list) {
+ if (!strcasecmp(gi->group, group) && (cw_strlen_zero(category)
|| !strcasecmp(gi->category, category)))
+ count++;
}
+ CW_LIST_UNLOCK(&groups);
return count;
}
int cw_app_group_match_get_count(char *groupmatch, char *category)
{
+ struct cw_group_info *gi = NULL;
regex_t regexbuf;
- struct cw_channel *chan;
int count = 0;
- char *test;
- char cat[80];
- char *s;
if (cw_strlen_zero(groupmatch))
return 0;
@@ -1110,22 +1127,51 @@
if (regcomp(®exbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
return 0;
- s = (!cw_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX;
- cw_copy_string(cat, s, sizeof(cat));
-
- chan = NULL;
- while ((chan = cw_channel_walk_locked(chan)) != NULL) {
- test = pbx_builtin_getvar_helper(chan, cat);
- if (test && !regexec(®exbuf, test, 0, NULL, 0))
+ CW_LIST_LOCK(&groups);
+ CW_LIST_TRAVERSE(&groups, gi, list) {
+ if (!regexec(®exbuf, gi->group, 0, NULL, 0) &&
(cw_strlen_zero(category) || !strcasecmp(gi->category, category)))
count++;
- cw_mutex_unlock(&chan->lock);
}
-
+ CW_LIST_UNLOCK(&groups);
+
regfree(®exbuf);
return count;
}
+int cw_app_group_discard(struct cw_channel *chan)
+{
+ struct cw_group_info *gi = NULL;
+
+ CW_LIST_LOCK(&groups);
+ CW_LIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
+ if (gi->chan == chan) {
+ CW_LIST_REMOVE_CURRENT(&groups, list);
+ free(gi);
+ }
+ }
+ CW_LIST_TRAVERSE_SAFE_END
+ CW_LIST_UNLOCK(&groups);
+
+ return 0;
+}
+
+int cw_app_group_list_lock(void)
+{
+ return CW_LIST_LOCK(&groups);
+}
+
+struct cw_group_info *cw_app_group_list_head(void)
+{
+ return CW_LIST_FIRST(&groups);
+}
+
+int cw_app_group_list_unlock(void)
+{
+ return CW_LIST_UNLOCK(&groups);
+}
+
+
int cw_separate_app_args(char *buf, char delim, int max_args, char **argv)
{
char *start;
Index: apps/app_groupcount.c
===================================================================
--- apps/app_groupcount.c (revision 5364)
+++ apps/app_groupcount.c (working copy)
@@ -244,10 +244,8 @@
{
#define FORMAT_STRING "%-25s %-20s %-20s\n"
- struct cw_channel *c = NULL;
int numchans = 0;
- struct cw_var_t *current;
- struct varshead *headp;
+ struct cw_group_info *gi = NULL;
regex_t regexbuf;
int havepattern = 0;
@@ -261,25 +259,17 @@
}
cw_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
- while ( (c = cw_channel_walk_locked(c)) != NULL) {
- headp=&c->varshead;
- CW_LIST_TRAVERSE(headp,current,entries) {
- if (!strncmp(cw_var_name(current),
GROUP_CATEGORY_PREFIX "_", strlen(GROUP_CATEGORY_PREFIX) + 1)) {
- if (!havepattern || !regexec(®exbuf,
cw_var_value(current), 0, NULL, 0)) {
- cw_cli(fd, FORMAT_STRING, c->name,
cw_var_value(current),
- (cw_var_name(current) +
strlen(GROUP_CATEGORY_PREFIX) + 1));
- numchans++;
- }
- } else if (!strcmp(cw_var_name(current),
GROUP_CATEGORY_PREFIX)) {
- if (!havepattern || !regexec(®exbuf,
cw_var_value(current), 0, NULL, 0)) {
- cw_cli(fd, FORMAT_STRING, c->name,
cw_var_value(current), "(default)");
- numchans++;
- }
- }
- }
- numchans++;
- cw_mutex_unlock(&c->lock);
+ cw_app_group_list_lock();
+
+ gi = cw_app_group_list_head();
+ while (gi) {
+ if (!havepattern || !regexec(®exbuf, gi->group, 0, NULL, 0))
{
+ cw_cli(fd, FORMAT_STRING, gi->chan->name, gi->group,
(cw_strlen_zero(gi->category) ? "(default)" : gi->category));
+ numchans++;
+ }
+ gi = CW_LIST_NEXT(gi, list);
}
+ cw_app_group_list_unlock();
if (havepattern)
regfree(®exbuf);
Index: funcs/func_groupcount.c
===================================================================
--- funcs/func_groupcount.c (revision 5364)
+++ funcs/func_groupcount.c (working copy)
@@ -71,23 +71,16 @@
static char *group_count_function_read(struct cw_channel *chan, int argc, char
**argv, char *buf, size_t len)
{
- int count;
- char group[80] = "";
- char category[80] = "";
- char *grp;
-
+ int count = -1;
+ char group[80] = "", category[80] = "";
+
cw_app_group_split_group(argv[0], group, sizeof(group), category,
sizeof(category));
- if (cw_strlen_zero(group)) {
- if ((grp = pbx_builtin_getvar_helper(chan, category)))
- cw_copy_string(group, grp, sizeof(group));
- else
- cw_log(LOG_NOTICE, "No group could be found for channel
'%s'\n", chan->name);
- }
+ if ((count = cw_app_group_get_count(group, category)) == -1)
+ cw_log(LOG_NOTICE, "No group could be found for channel
'%s'\n", chan->name);
+ else
+ snprintf(buf, len, "%d", count);
- count = cw_app_group_get_count(group, category);
- snprintf(buf, len, "%d", count);
-
return buf;
}
@@ -109,19 +102,26 @@
static char *group_function_read(struct cw_channel *chan, int argc, char
**argv, char *buf, size_t len)
{
- char varname[256];
- char *group;
+ struct cw_group_info *gi = NULL;
- if (argc > 0 && argv[0][0]) {
- snprintf(varname, sizeof(varname), "%s_%s",
GROUP_CATEGORY_PREFIX, argv[0]);
- } else {
- cw_copy_string(varname, GROUP_CATEGORY_PREFIX, sizeof(varname));
- }
+ cw_app_group_list_lock();
- group = pbx_builtin_getvar_helper(chan, varname);
- if (group)
- cw_copy_string(buf, group, len);
+ gi = cw_app_group_list_head();
+ while (gi) {
+ if (gi->chan != chan)
+ continue;
+ if (cw_strlen_zero(argv))
+ break;
+ if (!cw_strlen_zero(gi->category) && !strcasecmp(gi->category,
argv[0]))
+ break;
+ gi = CW_LIST_NEXT(gi, list);
+ }
+ if (gi)
+ cw_copy_string(buf, gi->group, len);
+
+ cw_app_group_list_unlock();
+
return buf;
}
@@ -141,29 +141,31 @@
static char *group_list_function_read(struct cw_channel *chan, int argc, char
**argv, char *buf, size_t len)
{
- struct cw_var_t *current;
- struct varshead *headp;
+struct cw_group_info *gi = NULL;
char tmp1[1024] = "";
char tmp2[1024] = "";
- headp=&chan->varshead;
- CW_LIST_TRAVERSE(headp,current,entries) {
- if (!strncmp(cw_var_name(current), GROUP_CATEGORY_PREFIX "_",
strlen(GROUP_CATEGORY_PREFIX) + 1)) {
- if (!cw_strlen_zero(tmp1)) {
- cw_copy_string(tmp2, tmp1, sizeof(tmp2));
- snprintf(tmp1, sizeof(tmp1), "%s %...@%s",
tmp2, cw_var_value(current), (cw_var_name(current) +
strlen(GROUP_CATEGORY_PREFIX) + 1));
- } else {
- snprintf(tmp1, sizeof(tmp1), "%...@%s",
cw_var_value(current), (cw_var_name(current) + strlen(GROUP_CATEGORY_PREFIX) +
1));
- }
- } else if (!strcmp(cw_var_name(current),
GROUP_CATEGORY_PREFIX)) {
- if (!cw_strlen_zero(tmp1)) {
- cw_copy_string(tmp2, tmp1, sizeof(tmp2));
- snprintf(tmp1, sizeof(tmp1), "%s %s", tmp2,
cw_var_value(current));
- } else {
- snprintf(tmp1, sizeof(tmp1), "%s",
cw_var_value(current));
- }
+ cw_app_group_list_lock();
+
+ for (gi = cw_app_group_list_head(); gi; gi = CW_LIST_NEXT(gi, list)) {
+ if (gi->chan != chan)
+ continue;
+ if (!cw_strlen_zero(tmp1)) {
+ cw_copy_string(tmp2, tmp1, sizeof(tmp2));
+ if (!cw_strlen_zero(gi->category))
+ snprintf(tmp1, sizeof(tmp1), "%s %...@%s",
tmp2, gi->group, gi->category);
+ else
+ snprintf(tmp1, sizeof(tmp1), "%s %s", tmp2,
gi->group);
+ } else {
+ if (!cw_strlen_zero(gi->category))
+ snprintf(tmp1, sizeof(tmp1), "%...@%s",
gi->group, gi->category);
+ else
+ snprintf(tmp1, sizeof(tmp1), "%s", gi->group);
}
}
+
+ cw_app_group_list_unlock();
+
cw_copy_string(buf, tmp1, len);
return buf;
}
Index: include/callweaver/app.h
===================================================================
--- include/callweaver/app.h (revision 5364)
+++ include/callweaver/app.h (working copy)
@@ -181,7 +181,12 @@
/* Read a file into callweaver */
char *cw_read_textfile(const char *file);
-#define GROUP_CATEGORY_PREFIX "GROUP"
+struct cw_group_info {
+ struct cw_channel *chan;
+ char *category;
+ char *group;
+ CW_LIST_ENTRY(cw_group_info) list;
+};
/*! Split a group string into group and category, returning a default category
if none is provided. */
int cw_app_group_split_group(char *data, char *group, int group_max, char
*category, int category_max);
@@ -195,7 +200,19 @@
/*! Get the current channel count of all groups that match the specified
pattern and category. */
int cw_app_group_match_get_count(char *groupmatch, char *category);
+/*! Discard all group counting for a channel */
+int cw_app_group_discard(struct cw_channel *chan);
+/*! Lock the group count list */
+int cw_app_group_list_lock(void);
+
+/*! Get the head of the group count list */
+struct cw_group_info *cw_app_group_list_head(void);
+
+/*! Unlock the group count list */
+int cw_app_group_list_unlock(void);
+
+
/*!
\brief Separate a string into arguments in an array
\param buf The string to be parsed (this must be a writable copy, as it will
be modified)
_______________________________________________
Callweaver-dev mailing list
[email protected]
http://lists.callweaver.org/mailman/listinfo/callweaver-dev