--- - 2007-03-26 06:12:21.239300000 +0200 +++ apps/app_queue.c 2006-12-05 13:15:14.000000000 +0100 @@ -219,6 +219,14 @@ " UNPAUSED | NOTFOUND\n" "Example: UnpauseQueueMember(|SIP/3000)\n"; +static char *app_spqm = "PenaltyQueueMember" ; +static char *app_spqm_synopsis = "Set the penalty for a queue member" ; +static char *app_spqm_descrip = +" PenaltyQueueMember([queuename]|interface[|penalty]):\n" +"Do set the penalty value for a queue member.\n" +"When there is no penalty specified, then it will set the penalty to 0.\n" +"Example: PenaltyQueueMember(|SIP/3000|100)\n"; + /*! \brief Persistent Members astdb family */ static const char *pm_family = "/Queue/PersistentMembers"; /* The maximum lengh of each persistent member queue database entry */ @@ -2513,6 +2521,43 @@ return RESULT_FAILURE; } +static int set_member_penalty(char *queuename, char *interface, int penalty) +{ + int found = 0; + struct ast_call_queue *q; + struct member *mem; + + if (ast_strlen_zero(queuename)) + ast_queue_log("NONE", "NONE", interface, "PENALTY", "%d", penalty); + + ast_mutex_lock(&qlock); + for (q = queues ; q ; q = q->next) { + ast_mutex_lock(&q->lock); + if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) { + if ((mem = interface_exists(q, interface))) { + found++; + + mem->penalty = penalty; + + ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty); + + manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty", + "Queue: %s\r\n" + "Location: %s\r\n" + "Penalty: %d\r\n", + q->name, mem->interface, penalty); + } + } + ast_mutex_unlock(&q->lock); + } + ast_mutex_unlock(&qlock); + + if (found) + return RESULT_SUCCESS; + else + return RESULT_FAILURE; +} + /* Reload dynamic queue members persisted into the astdb */ static void reload_queue_members(void) { @@ -2715,6 +2760,52 @@ return 0; } +static int spqm_exec(struct ast_channel *chan, void *data) +{ + struct localuser *u; + char *parse; + int penalty = 0; + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(queuename); + AST_APP_ARG(interface); + AST_APP_ARG(penalty); + ); + + if (ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "PenaltyQueueMember requires an argument ([queuename]|interface[|penalty])\n"); + return -1; + } + + LOCAL_USER_ADD(u); + + if (!(parse = ast_strdupa(data))) { + ast_log(LOG_WARNING, "Memory Error!\n"); + LOCAL_USER_REMOVE(u); + return -1; + } + + AST_STANDARD_APP_ARGS(args, parse); + + if (args.penalty) { + penalty = atoi(args.penalty); + } + + if (ast_strlen_zero(args.interface)) { + ast_log(LOG_WARNING, "Missing interface argument to PenaltyQueueMember ([queuename]|interface[|penalty])\n"); + LOCAL_USER_REMOVE(u); + return -1; + } + + if (set_member_penalty(args.queuename, args.interface, penalty)) { + ast_log(LOG_WARNING, "Attempt to set penalty for interface %s, not found\n", args.interface); + LOCAL_USER_REMOVE(u); + return -1; + } + + LOCAL_USER_REMOVE(u); + return 0; +} + static int rqm_exec(struct ast_channel *chan, void *data) { int res=-1; @@ -3609,6 +3700,30 @@ return 0; } +static int manager_penalty_queue_member(struct mansession *s, struct message *m) +{ + char *queuename, *interface, *penalty_s; + int penalty; + + interface = astman_get_header(m, "Interface"); + penalty_s = astman_get_header(m, "Penalty"); + queuename = astman_get_header(m, "Queue"); /* Optional - if not supplied, set the penalty value for the given Interface in all queues */ + + if (ast_strlen_zero(interface) || ast_strlen_zero(penalty_s)) { + astman_send_error(s, m, "Need 'Interface' and 'Penalty' parameters."); + return 0; + } + + penalty = atoi(penalty_s); + + if (set_member_penalty(queuename, interface, penalty)) + astman_send_error(s, m, "Interface not found"); + else + astman_send_ack(s, m, "Interface penalty set successfully"); + + return 0; +} + static int handle_add_queue_member(int fd, int argc, char *argv[]) { char *queuename, *interface; @@ -3762,6 +3877,72 @@ return NULL; } +static int handle_penalty_queue_member(int fd, int argc, char *argv[]) +{ + char *queuename, *interface, *s_penalty; + int penalty = 0; + + if (argc != 7) { + return RESULT_SHOWUSAGE; + } else if (strcmp(argv[4], "from")) { + return RESULT_SHOWUSAGE; + } + + queuename = argv[5]; + interface = argv[3]; + s_penalty = argv[6]; + penalty = atoi(s_penalty); + + switch (set_member_penalty(queuename, interface, penalty)) { + case RESULT_SUCCESS: + ast_cli(fd, "Set penalty on interface '%s' from queue '%s'\n", interface, queuename); + return RESULT_SUCCESS; + case RESULT_FAILURE: + ast_cli(fd, "Failed to set penalty on interface '%s' from queue '%s'\n", interface, queuename); + return RESULT_FAILURE; + default: + return RESULT_FAILURE; + } +} + +static char *complete_penalty_queue_member(char *line, char *word, int pos, int state) +{ + int which = 0; + struct ast_call_queue *q; + struct member *m; + + /* 0 - penalty; 1 - queue; 2 - member; 3 - ; 4 - from; 5 - */ + if ((pos > 5) || (pos < 3)) { + return NULL; + } + if (pos == 4) { + if (state == 0) { + return strdup("from"); + } else { + return NULL; + } + } + + if (pos == 5) { + /* No need to duplicate code */ + return complete_queue(line, word, pos, state); + } + + if (queues != NULL) { + for (q = queues ; q ; q = q->next) { + ast_mutex_lock(&q->lock); + for (m = q->members ; m ; m = m->next) { + if (++which > state) { + ast_mutex_unlock(&q->lock); + return strdup(m->interface); + } + } + ast_mutex_unlock(&q->lock); + } + } + return NULL; +} + static char show_queues_usage[] = "Usage: show queues\n" " Provides summary information on call queues.\n"; @@ -3792,6 +3973,13 @@ { "remove", "queue", "member", NULL }, handle_remove_queue_member, "Removes a channel from a specified queue", rqm_cmd_usage, complete_remove_queue_member }; +static char pqm_cmd_usage[] = +"Usage: penalty queue member from \n"; + +static struct ast_cli_entry cli_penalty_queue_member = { + { "penalty", "queue", "member", NULL }, handle_penalty_queue_member, + "Set penalty for a channel from a specified queue", pqm_cmd_usage, complete_penalty_queue_member }; + int unload_module(void) { int res; @@ -3800,16 +3988,19 @@ res |= ast_cli_unregister(&cli_show_queues); res |= ast_cli_unregister(&cli_add_queue_member); res |= ast_cli_unregister(&cli_remove_queue_member); + res |= ast_cli_unregister(&cli_penalty_queue_member); res |= ast_manager_unregister("Queues"); res |= ast_manager_unregister("QueueStatus"); res |= ast_manager_unregister("QueueAdd"); res |= ast_manager_unregister("QueueRemove"); res |= ast_manager_unregister("QueuePause"); + res |= ast_manager_unregister("QueuePenalty"); ast_devstate_del(statechange_queue, NULL); res |= ast_unregister_application(app_aqm); res |= ast_unregister_application(app_rqm); res |= ast_unregister_application(app_pqm); res |= ast_unregister_application(app_upqm); + res |= ast_unregister_application(app_spqm); res |= ast_custom_function_unregister(&queueagentcount_function); res |= ast_unregister_application(app); @@ -3827,16 +4018,19 @@ res |= ast_cli_register(&cli_show_queues); res |= ast_cli_register(&cli_add_queue_member); res |= ast_cli_register(&cli_remove_queue_member); + res |= ast_cli_register(&cli_penalty_queue_member); res |= ast_devstate_add(statechange_queue, NULL); res |= ast_manager_register( "Queues", 0, manager_queues_show, "Queues" ); res |= ast_manager_register( "QueueStatus", 0, manager_queues_status, "Queue Status" ); res |= ast_manager_register( "QueueAdd", EVENT_FLAG_AGENT, manager_add_queue_member, "Add interface to queue." ); res |= ast_manager_register( "QueueRemove", EVENT_FLAG_AGENT, manager_remove_queue_member, "Remove interface from queue." ); res |= ast_manager_register( "QueuePause", EVENT_FLAG_AGENT, manager_pause_queue_member, "Makes a queue member temporarily unavailable" ); + res |= ast_manager_register( "QueuePenalty", EVENT_FLAG_AGENT, manager_penalty_queue_member, "Set the penalty for a queue member" ); res |= ast_register_application(app_aqm, aqm_exec, app_aqm_synopsis, app_aqm_descrip) ; res |= ast_register_application(app_rqm, rqm_exec, app_rqm_synopsis, app_rqm_descrip) ; res |= ast_register_application(app_pqm, pqm_exec, app_pqm_synopsis, app_pqm_descrip) ; res |= ast_register_application(app_upqm, upqm_exec, app_upqm_synopsis, app_upqm_descrip) ; + res |= ast_register_application(app_spqm, spqm_exec, app_spqm_synopsis, app_spqm_descrip) ; res |= ast_custom_function_register(&queueagentcount_function); if (!res) {