Better call distribution algorithm
This commit is contained in:
parent
fd7c663caf
commit
17658c5edf
|
@ -91,4 +91,10 @@ devices=2 ;number of concurrent calls (B-Channels) on this controller
|
||||||
; 65535 - suppres invocation code
|
; 65535 - suppres invocation code
|
||||||
;mwimailbox=12345 ;',' separated list of mailboxes for MWI in format:
|
;mwimailbox=12345 ;',' separated list of mailboxes for MWI in format:
|
||||||
; mailbox[:controlling user number[:controlling user provided number]][@context]
|
; mailbox[:controlling user number[:controlling user provided number]][@context]
|
||||||
|
;hlimit=10 ;Do not use this controller for outgoing calls if less than 'hlimit' free channels is
|
||||||
|
;left on this controller.
|
||||||
|
;slimit=10 ;Try to use for outgoing calls other controller in group if less than 'slimit' free
|
||||||
|
;channels is left on this controller. Always try to 'fill up' the controller with
|
||||||
|
;smalest number in group. Create call if less than 'slimit' free channels left and
|
||||||
|
;no other controller with respect to free channel count was found in group.
|
||||||
|
|
||||||
|
|
68
chan_capi.c
68
chan_capi.c
|
@ -211,7 +211,9 @@ static char global_mohinterpret[MAX_MUSICCLASS] = "default";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* local prototypes */
|
/* local prototypes */
|
||||||
#define CC_B_INTERFACE_NOT_FREE(__x__) (((__x__)->used) || ((__x__)->channeltype != CAPI_CHANNELTYPE_B))
|
#define CC_B_INTERFACE_NOT_FREE(__x__) (((__x__)->used) || \
|
||||||
|
((__x__)->channeltype != CAPI_CHANNELTYPE_B) || \
|
||||||
|
(capi_controllers[(__x__)->controller]->nfreebchannels < capi_controllers[(__x__)->controller]->nfreebchannelsHardThr))
|
||||||
|
|
||||||
static int pbx_capi_hold(struct ast_channel *c, char *param);
|
static int pbx_capi_hold(struct ast_channel *c, char *param);
|
||||||
static int pbx_capi_retrieve(struct ast_channel *c, char *param);
|
static int pbx_capi_retrieve(struct ast_channel *c, char *param);
|
||||||
|
@ -232,7 +234,7 @@ static void pbx_capi_add_diva_protocol_independent_extension(
|
||||||
static void pbx_capi_interface_status_changed(int controller, diva_status_interface_state_t newInterfaceState);
|
static void pbx_capi_interface_status_changed(int controller, diva_status_interface_state_t newInterfaceState);
|
||||||
static void pbx_capi_hw_status_changed(int controller, diva_status_hardware_state_t newHwState);
|
static void pbx_capi_hw_status_changed(int controller, diva_status_hardware_state_t newHwState);
|
||||||
#endif
|
#endif
|
||||||
static int pbx_capi_check_controller_status(struct capi_pvt *currentChannel, ast_group_t capigroup);
|
static int pbx_capi_check_controller_status(int controller);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* B protocol settings
|
* B protocol settings
|
||||||
|
@ -2440,7 +2442,7 @@ static struct ast_channel *
|
||||||
pbx_capi_request(const char *type, int format, void *data, int *cause)
|
pbx_capi_request(const char *type, int format, void *data, int *cause)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct capi_pvt *i;
|
struct capi_pvt *i, *bestChannel;
|
||||||
struct ast_channel *tmp = NULL;
|
struct ast_channel *tmp = NULL;
|
||||||
char *dest, *interface, *param, *ocid;
|
char *dest, *interface, *param, *ocid;
|
||||||
char buffer[CAPI_MAX_STRING];
|
char buffer[CAPI_MAX_STRING];
|
||||||
|
@ -2484,7 +2486,7 @@ pbx_capi_request(const char *type, int format, void *data, int *cause)
|
||||||
|
|
||||||
cc_mutex_lock(&iflock);
|
cc_mutex_lock(&iflock);
|
||||||
|
|
||||||
for (i = capi_iflist; i; i = i->next) {
|
for (i = capi_iflist, bestChannel = 0; i; i = i->next) {
|
||||||
if (CC_B_INTERFACE_NOT_FREE(i)) {
|
if (CC_B_INTERFACE_NOT_FREE(i)) {
|
||||||
/* if already in use or no real channel */
|
/* if already in use or no real channel */
|
||||||
continue;
|
continue;
|
||||||
|
@ -2495,7 +2497,7 @@ pbx_capi_request(const char *type, int format, void *data, int *cause)
|
||||||
if (i->controller != controller) {
|
if (i->controller != controller) {
|
||||||
/* keep on running! */
|
/* keep on running! */
|
||||||
continue;
|
continue;
|
||||||
} else if (pbx_capi_check_controller_status(i, 0) != 0) {
|
} else if (pbx_capi_check_controller_status(i->controller) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2503,16 +2505,32 @@ pbx_capi_request(const char *type, int format, void *data, int *cause)
|
||||||
if (interface[0] == 'g') {
|
if (interface[0] == 'g') {
|
||||||
if ((i->group & capigroup) == 0)
|
if ((i->group & capigroup) == 0)
|
||||||
continue; /* not in group, keep on running! */
|
continue; /* not in group, keep on running! */
|
||||||
if (pbx_capi_check_controller_status(i, capigroup) != 0)
|
if (pbx_capi_check_controller_status(i->controller) < 0)
|
||||||
continue; /* not active or better interface found, keep on running! */
|
continue; /* not active or better interface found, keep on running! */
|
||||||
|
if (capi_controllers[i->controller]->nfreebchannelsSoftThr != 0) {
|
||||||
|
if (bestChannel == 0) {
|
||||||
|
bestChannel = i;
|
||||||
|
} else if (i->controller != bestChannel->controller) {
|
||||||
|
int idiff = capi_controllers[i->controller]->nfreebchannels - capi_controllers[i->controller]->nfreebchannelsSoftThr;
|
||||||
|
int bdiff = capi_controllers[bestChannel->controller]->nfreebchannels - capi_controllers[bestChannel->controller]->nfreebchannelsSoftThr;
|
||||||
|
int c = (i->controller < bestChannel->controller);
|
||||||
|
|
||||||
|
if ((c && (idiff >= 0)) || ((bdiff < 0) && (idiff >= 0)) || ((bdiff < 0) && (idiff > bdiff))) {
|
||||||
|
bestChannel = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue; /* Continue search for best channel */
|
||||||
|
}
|
||||||
} else if (strcmp(interface, i->name) != 0) {
|
} else if (strcmp(interface, i->name) != 0) {
|
||||||
/* DIAL(CAPI/<interface-name>/...) */
|
/* DIAL(CAPI/<interface-name>/...) */
|
||||||
/* keep on running! */
|
/* keep on running! */
|
||||||
continue;
|
continue;
|
||||||
} else if (pbx_capi_check_controller_status(i, 0) != 0) {
|
} else if (pbx_capi_check_controller_status(i->controller) < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found_best_channel:
|
||||||
/* when we come here, we found a free controller match */
|
/* when we come here, we found a free controller match */
|
||||||
cc_copy_string(i->dnid, dest, sizeof(i->dnid));
|
cc_copy_string(i->dnid, dest, sizeof(i->dnid));
|
||||||
tmp = capi_new(i, AST_STATE_RESERVED,
|
tmp = capi_new(i, AST_STATE_RESERVED,
|
||||||
|
@ -2532,6 +2550,11 @@ pbx_capi_request(const char *type, int format, void *data, int *cause)
|
||||||
cc_mutex_unlock(&iflock);
|
cc_mutex_unlock(&iflock);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
if (bestChannel != 0) {
|
||||||
|
i = bestChannel;
|
||||||
|
goto found_best_channel;
|
||||||
|
}
|
||||||
|
|
||||||
cc_mutex_unlock(&iflock);
|
cc_mutex_unlock(&iflock);
|
||||||
cc_verbose(2, 0, VERBOSE_PREFIX_3 "didn't find " CC_MESSAGE_NAME
|
cc_verbose(2, 0, VERBOSE_PREFIX_3 "didn't find " CC_MESSAGE_NAME
|
||||||
" device for interface '%s'\n", interface);
|
" device for interface '%s'\n", interface);
|
||||||
|
@ -7700,6 +7723,8 @@ int mkif(struct cc_capi_conf *conf)
|
||||||
capi_controllers[unit]->used = 1;
|
capi_controllers[unit]->used = 1;
|
||||||
capi_controllers[unit]->ecPath = conf->echocancelpath;
|
capi_controllers[unit]->ecPath = conf->echocancelpath;
|
||||||
capi_controllers[unit]->ecOnTransit = conf->econtransitconn;
|
capi_controllers[unit]->ecOnTransit = conf->econtransitconn;
|
||||||
|
capi_controllers[unit]->nfreebchannelsHardThr = conf->hlimit;
|
||||||
|
capi_controllers[unit]->nfreebchannelsSoftThr = conf->slimit;
|
||||||
mwiController = capi_controllers[unit];
|
mwiController = capi_controllers[unit];
|
||||||
|
|
||||||
tmp->controller = unit;
|
tmp->controller = unit;
|
||||||
|
@ -8627,6 +8652,8 @@ static int conf_interface(struct cc_capi_conf *conf, struct ast_variable *v)
|
||||||
CONF_INTEGER_SAFE(conf->mwifacptynrpres, "mwifacptynrpres", 0, 0x7f)
|
CONF_INTEGER_SAFE(conf->mwifacptynrpres, "mwifacptynrpres", 0, 0x7f)
|
||||||
CONF_INTEGER_SAFE(conf->mwibasicservice, "mwibasicservice", 0, 0xff)
|
CONF_INTEGER_SAFE(conf->mwibasicservice, "mwibasicservice", 0, 0xff)
|
||||||
CONF_INTEGER_SAFE(conf->mwiinvocation, "mwiinvocation", 0, 0xffff)
|
CONF_INTEGER_SAFE(conf->mwiinvocation, "mwiinvocation", 0, 0xffff)
|
||||||
|
CONF_INTEGER_SAFE(conf->hlimit, "hlimit", 0, 0xff)
|
||||||
|
CONF_INTEGER_SAFE(conf->slimit, "slimit", 0, 0xff)
|
||||||
if (!strcasecmp(v->name, "mwimailbox")) {
|
if (!strcasecmp(v->name, "mwimailbox")) {
|
||||||
conf->mwimailbox = ast_strdup(v->value);
|
conf->mwimailbox = ast_strdup(v->value);
|
||||||
continue;
|
continue;
|
||||||
|
@ -9194,12 +9221,9 @@ static void pbx_capi_hw_status_changed(int controller, diva_status_hardware_stat
|
||||||
\note The core runs twice over the interface list, but this allows to preserve
|
\note The core runs twice over the interface list, but this allows to preserve
|
||||||
the structure of the original code which uses this function.
|
the structure of the original code which uses this function.
|
||||||
*/
|
*/
|
||||||
static int pbx_capi_check_controller_status(struct capi_pvt *currentChannel, ast_group_t capigroup)
|
static int pbx_capi_check_controller_status(int capiController)
|
||||||
{
|
{
|
||||||
#ifdef DIVA_STATUS
|
#ifdef DIVA_STATUS
|
||||||
int capiController = currentChannel->controller;
|
|
||||||
struct capi_pvt *newChannel;
|
|
||||||
|
|
||||||
if (capi_controllers[capiController]->interfaceState == (int)DivaStatusInterfaceStateOK) /* known, OK */
|
if (capi_controllers[capiController]->interfaceState == (int)DivaStatusInterfaceStateOK) /* known, OK */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -9207,28 +9231,10 @@ static int pbx_capi_check_controller_status(struct capi_pvt *currentChannel, ast
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The state of interface is unknown. Look if it is other interface which belongs
|
Unknown interface state
|
||||||
to requested group with known state and free capi_pvt associated with this interface
|
|
||||||
*/
|
|
||||||
if ((capigroup == 0) || (diva_status_available() != 0))
|
|
||||||
return (0); /* Status information not available, use this interface */
|
|
||||||
|
|
||||||
for (newChannel = currentChannel->next; (newChannel != 0); newChannel = newChannel->next) {
|
|
||||||
if (CC_B_INTERFACE_NOT_FREE(newChannel)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ((newChannel->controller != capiController) &&
|
|
||||||
((newChannel->group & capigroup) != 0) &&
|
|
||||||
(capi_controllers[newChannel->controller]->interfaceState == (int)DivaStatusInterfaceStateOK)) {
|
|
||||||
return (-1); /* Found better interface */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
No better channel found, use this interface
|
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
chan_capi.h
10
chan_capi.h
|
@ -642,6 +642,9 @@ struct cc_capi_conf {
|
||||||
int mwiinvocation;
|
int mwiinvocation;
|
||||||
|
|
||||||
char* mwimailbox;
|
char* mwimailbox;
|
||||||
|
|
||||||
|
int hlimit;
|
||||||
|
int slimit;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cc_capi_controller;
|
struct cc_capi_controller;
|
||||||
|
@ -671,6 +674,13 @@ struct cc_capi_controller {
|
||||||
int nbchannels;
|
int nbchannels;
|
||||||
/* free bchans */
|
/* free bchans */
|
||||||
int nfreebchannels;
|
int nfreebchannels;
|
||||||
|
/* Controller considered BUSY amount if free channels below
|
||||||
|
of this level */
|
||||||
|
int nfreebchannelsHardThr;
|
||||||
|
/* If amount of free channels is below this level then
|
||||||
|
try to allocate call on other controler in group
|
||||||
|
where this level is not reached or difference is less */
|
||||||
|
int nfreebchannelsSoftThr;
|
||||||
/* features: */
|
/* features: */
|
||||||
int broadband;
|
int broadband;
|
||||||
int dtmf;
|
int dtmf;
|
||||||
|
|
Loading…
Reference in New Issue