Better call distribution algorithm

This commit is contained in:
MelwareDE 2010-10-26 22:22:25 +00:00
parent fd7c663caf
commit 17658c5edf
3 changed files with 53 additions and 31 deletions

View File

@ -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.

View File

@ -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;
} }

View File

@ -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;