/*----------------------------------------------------------------------------*/
/* Xymon message daemon.                                                      */
/*                                                                            */
/* Client backend module for MQ collector                                     */
/*                                                                            */
/* Copyright (C) 2009-2011 Henrik Storner <henrik@hswn.dk>                    */
/*                                                                            */
/* This program is released under the GNU General Public License (GPL),       */
/* version 2. See the file "COPYING" for details.                             */
/*                                                                            */
/*----------------------------------------------------------------------------*/

static char mqcollect_rcsid[] = "$Id: mqcollect.c 7060 2012-07-14 16:32:11Z storner $";

void mqcollect_flush_status(int color, char *fromline, time_t timestamp, 
			    char *hostname, char *qmid,
			    strbuffer_t *redsummary, strbuffer_t *yellowsummary, strbuffer_t *greensummary,
			    char *clienttext)
{
	char *groups;
	char msgline[1024];

	/* Generate the status message */
	groups = getalertgroups();
	init_status(color);
	if (groups) sprintf(msgline, "status/group:%s ", groups); else strcpy(msgline, "status ");
	addtostatus(msgline);
	sprintf(msgline, "%s.mq %s %s\n", 
		hostname, 
		colorname(color), ctime(&timestamp));
	addtostatus(msgline);
	if (STRBUFLEN(redsummary) > 0) {
		addtostrstatus(redsummary);
		addtostatus("\n");
	}
	if (STRBUFLEN(yellowsummary) > 0) {
		addtostrstatus(yellowsummary);
		addtostatus("\n");
	}
	if (STRBUFLEN(greensummary) > 0) {
		addtostrstatus(greensummary);
		addtostatus("\n");
	}
	addtostatus(clienttext);
	addtostatus("\n");
	addtostatus(fromline);
	finish_status();
}

void handle_mqcollect_client(char *hostname, char *clienttype, enum ostype_t os, 
				void *hinfo, char *sender, time_t timestamp,
				char *clientdata)
{
	char *qmline = "Starting MQSC for queue manager ";
	strbuffer_t *redsummary = newstrbuffer(0);
	strbuffer_t *yellowsummary = newstrbuffer(0);
	strbuffer_t *greensummary = newstrbuffer(0);
	char *bol, *eoln, *clienttext;
	int color = COL_GREEN;
	char fromline[1024], msgline[1024];
	char *qmid = NULL, *qnam = NULL; int qlen = -1, qage = -1; char *chnnam = NULL, *chnstatus = NULL;
	enum { PARSING_QL, PARSING_QS, PARSING_CHS, PARSER_FLOAT } pstate = PARSER_FLOAT;
	int lastline = 0;

	sprintf(fromline, "\nStatus message received from %s\n", sender);

	bol = strchr(clientdata, '\n'); if (bol) bol++; clienttext = bol;
	while (bol) {
		eoln = strchr(bol, '\n'); if (eoln) *eoln = '\0'; else lastline = 1;
		bol += strspn(bol, " \t");

		if (strncmp(bol, qmline, strlen(qmline)) == 0) {
			char *p;

			if (qmid) xfree(qmid);
			qmid = strdup(bol+strlen(qmline));
			p = strrchr(qmid, '.'); if (p) *p = '\0';
		}

		else if ( (strncmp(bol, "AMQ8409:", 8) == 0) ||		/* "ql" command - Queue details, incl. depth */
		          (strncmp(bol, "AMQ8450:", 8) == 0) ||		/* "qs" command - Queue status */
		          (strncmp(bol, "AMQ8417:", 8) == 0) ||		/* "chs" command - Channel status */
			  lastline                              ) {

			if ( ((pstate == PARSING_QL) || (pstate == PARSING_QS)) && qmid && qnam && (qlen >= 0)) {
				/* Got a full queue depth status */
				int warnlen, critlen, warnage, critage;
				char *trackid;
				get_mqqueue_thresholds(hinfo, clienttype, qmid, qnam, &warnlen, &critlen, &warnage, &critage, &trackid);

				if ((critlen != -1) && (qlen >= critlen)) {
					color = COL_RED;
					sprintf(msgline, "&red Queue %s:%s has depth %d (critical: %d, warn: %d)\n",
						qmid, qnam, qlen, critlen, warnlen);
					addtobuffer(redsummary, msgline);
				}
				else if ((warnlen != -1) && (qlen >= warnlen)) {
					if (color < COL_YELLOW) color = COL_YELLOW;
					sprintf(msgline, "&yellow Queue %s:%s has depth %d (warn: %d, critical: %d)\n",
						qmid, qnam, qlen, warnlen, critlen);
					addtobuffer(yellowsummary, msgline);
				}
				else if ((warnlen != -1) || (critlen != -1)) {
					sprintf(msgline, "&green Queue %s:%s has depth %d (warn: %d, critical: %d)\n",
						qmid, qnam, qlen, warnlen, critlen);
					addtobuffer(greensummary, msgline);
				}

				if ((pstate == PARSING_QS) && (qage >= 0)) {
					if ((critage != -1) && (qage >= critage)) {
						color = COL_RED;
						sprintf(msgline, "&red Queue %s:%s has age %d (critical: %d, warn: %d)\n",
								qmid, qnam, qage, critage, warnage);
						addtobuffer(redsummary, msgline);
					}
					else if ((warnage != -1) && (qage >= warnage)) {
						if (color < COL_YELLOW) color = COL_YELLOW;
						sprintf(msgline, "&yellow Queue %s:%s has age %d (warn: %d, critical: %d)\n",
								qmid, qnam, qage, warnage, critage);
						addtobuffer(yellowsummary, msgline);
					}
					else if ((warnage != -1) || (critage != -1)) {
						sprintf(msgline, "&green Queue %s:%s has age %d (warn: %d, critical: %d)\n",
								qmid, qnam, qage, warnage, critage);
						addtobuffer(greensummary, msgline);
					}
				}

				if (trackid) {
					/* FIXME: Send "data" message for creating queue-length RRD */
				}

				pstate = PARSER_FLOAT;
			}

			if ((pstate == PARSING_CHS) && qmid && chnnam && chnstatus) {
				/* Got a full channel status */
				int chncolor;

				if (get_mqchannel_params(hinfo, clienttype, qmid, chnnam, chnstatus, &chncolor)) {
					if (chncolor > color) color = chncolor;
					switch (chncolor) {
						case COL_RED:
							sprintf(msgline, "&red Channel %s:%s has status %s\n", qmid, chnnam, chnstatus);
							addtobuffer(redsummary, msgline);
							break;
						case COL_YELLOW:
							sprintf(msgline, "&yellow Channel %s:%s has status %s\n", qmid, chnnam, chnstatus);
							addtobuffer(yellowsummary, msgline);
							break;
						case COL_GREEN:
							sprintf(msgline, "&green Channel %s:%s has status %s\n", qmid, chnnam, chnstatus);
							addtobuffer(greensummary, msgline);
							break;
					}
				}

				pstate = PARSER_FLOAT;
			}

			if (qnam) xfree(qnam);
			qlen = qage = -1;
			if (chnnam) xfree(chnnam);
			if (chnstatus) xfree(chnstatus);

			if (strncmp(bol, "AMQ8409:", 8) == 0) pstate = PARSING_QL;
			else if (strncmp(bol, "AMQ8450:", 8) == 0) pstate = PARSING_QS;
			else if (strncmp(bol, "AMQ8417:", 8) == 0) pstate = PARSING_CHS;
			else pstate = PARSER_FLOAT;
		}
		else if ((pstate == PARSING_QL) || (pstate == PARSING_QS)) {
			char *bdup = strdup(bol);
			char *tok = strtok(bdup, " \t");
			while (tok) {
				if (strncmp(tok, "QUEUE(", 6) == 0) {
					char *p;

					qnam = strdup(tok+6);
					p = strchr(qnam, ')');
					if (p) *p = '\0';
				}
				else if (strncmp(tok, "CURDEPTH(", 9) == 0) {
					qlen = atoi(tok+9);
				}
				else if (strncmp(tok, "MSGAGE(", 7) == 0) {
					if (isdigit(*(tok+7))) qage = atoi(tok+7);
				}

				tok = strtok(NULL, " \t");
			}

			xfree(bdup);
		}
		else if (pstate == PARSING_CHS) {
			char *bdup = strdup(bol);
			char *tok = strtok(bdup, " \t");
			while (tok) {
				if (strncmp(tok, "CHANNEL(", 8) == 0) {
					char *p;

					chnnam = strdup(tok+8);
					p = strchr(chnnam, ')');
					if (p) *p = '\0';
				}
				else if (strncmp(tok, "STATUS(", 7) == 0) {
					char *p;

					chnstatus = strdup(tok+7);
					p = strchr(chnstatus, ')');
					if (p) *p = '\0';
				}

				tok = strtok(NULL, " \t");
			}
			xfree(bdup);
		}

		if (eoln) {
			*eoln = '\n';
			bol = eoln+1;
		}
		else
			bol = NULL;
	}

	mqcollect_flush_status(color, fromline, timestamp, 
			       hostname, qmid,
			       redsummary, yellowsummary, greensummary,
			       clienttext);

	if (qmid) xfree(qmid);
	freestrbuffer(greensummary);
	freestrbuffer(yellowsummary);
	freestrbuffer(redsummary);
}

