]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stats admin: reduce memcmp()/strcmp() calls on status codes
authorCyril Bonté <cyril.bonte@free.fr>
Wed, 4 Apr 2012 10:57:21 +0000 (12:57 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 5 Apr 2012 07:58:27 +0000 (09:58 +0200)
memcmp()/strcmp() calls were needed in different parts of code to determine
the status code. Each new status code introduces new calls, which can become
inefficient and source of bugs.
This patch reorganizes the code to rely on a numeric status code internally
and to be hopefully more generic.

include/proto/dumpstats.h
include/types/proto_http.h
include/types/stream_interface.h
src/dumpstats.c
src/proto_http.c

index 4c3837b424e2272b31d1a91c0e5f0dfbceb46245..319ab48ec89fcddf322e9edc4a724af7647f3436 100644 (file)
 #define STAT_CLI_O_TAB  8   /* dump tables */
 #define STAT_CLI_O_CLR  9   /* clear tables */
 
-/* status codes (strictly 4 chars) used in the URL to display a message */
-#define STAT_STATUS_UNKN "UNKN"        /* an unknown error occured, shouldn't happen */
-#define STAT_STATUS_DONE "DONE"        /* the action is successful */
-#define STAT_STATUS_PART "PART"        /* the action is partially successful */
-#define STAT_STATUS_NONE "NONE"        /* nothing happened (no action chosen or servers state didn't change) */
-#define STAT_STATUS_ERRP "ERRP"        /* an error occured due to invalid values in parameters */
-#define STAT_STATUS_EXCD "EXCD"        /* an error occured because the buffer couldn't store all data */
-#define STAT_STATUS_DENY "DENY"        /* action denied */
-
 extern struct si_applet http_stats_applet;
 
 void stats_io_handler(struct stream_interface *si);
index a7b16aa257d298904cb6bec71f85c6259b1f3fbb..51f321ece9481b2624406b4f20b8159bf94001e3 100644 (file)
@@ -258,6 +258,19 @@ enum {
        ST_ADM_ACTION_ENABLE,
 };
 
+/* status codes available for the stats admin page */
+enum {
+       STAT_STATUS_INIT = 0,
+       STAT_STATUS_DENY,       /* action denied */
+       STAT_STATUS_DONE,       /* the action is successful */
+       STAT_STATUS_ERRP,       /* an error occured due to invalid values in parameters */
+       STAT_STATUS_EXCD,       /* an error occured because the buffer couldn't store all data */
+       STAT_STATUS_NONE,       /* nothing happened (no action chosen or servers state didn't change) */
+       STAT_STATUS_PART,       /* the action is partially successful */
+       STAT_STATUS_UNKN,       /* an unknown error occured, shouldn't happen */
+       STAT_STATUS_SIZE
+};
+
 /* This is an HTTP message, as described in RFC2616. It can be either a request
  * message or a response message.
  *
index 5acbd5743c3b6b855627a46d3cd9859a1e8261d2..711394ada389dac33cc5e2eebc4620dd7a59a61f 100644 (file)
@@ -149,7 +149,7 @@ struct stream_interface {
                                int px_st;              /* STAT_PX_ST* */
                                unsigned int flags;     /* STAT_* */
                                int iid, type, sid;     /* proxy id, type and service id if bounding of stats is enabled */
-                               const char *st_code;    /* pointer to the status code returned by an action */
+                               int st_code;            /* the status code returned by an action */
                        } stats;
                        struct {
                                struct bref bref;       /* back-reference from the session being dumped */
index 3f88fc50734a93a6154eaec8c48787e92d37b9cc..dc3ac752be84c9660006983a9001c6705b8e7c8f 100644 (file)
@@ -114,6 +114,8 @@ enum {
        STAT_PX_ST_FIN,
 };
 
+extern const char *stat_status_codes[];
+
 /* This function is called from the session-level accept() in order to instanciate
  * a new stats socket. It returns a positive value upon success, 0 if the connection
  * needs to be closed and ignored, or a negative value upon critical failure.
@@ -1686,7 +1688,12 @@ static int stats_http_redir(struct stream_interface *si, struct uri_auth *uri)
                        "Content-Type: text/plain\r\n"
                        "Connection: close\r\n"
                        "Location: %s;st=%s",
-                       uri->uri_prefix, si->applet.ctx.stats.st_code);
+                       uri->uri_prefix,
+                       ((si->applet.ctx.stats.st_code > STAT_STATUS_INIT) &&
+                        (si->applet.ctx.stats.st_code < STAT_STATUS_SIZE) &&
+                        stat_status_codes[si->applet.ctx.stats.st_code]) ?
+                               stat_status_codes[si->applet.ctx.stats.st_code] :
+                               stat_status_codes[STAT_STATUS_UNKN]);
                chunk_printf(&msg, "\r\n\r\n");
 
                if (buffer_feed_chunk(si->ib, &msg) >= 0)
@@ -2023,29 +2030,30 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
                             );
 
                        if (si->applet.ctx.stats.st_code) {
-                               if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_DONE) == 0) {
+                               switch (si->applet.ctx.stats.st_code) {
+                               case STAT_STATUS_DONE:
                                        chunk_printf(&msg,
                                                     "<p><div class=active3>"
                                                     "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
                                                     "Action processed successfully."
                                                     "</div>\n", uri->uri_prefix);
-                               }
-                               else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_NONE) == 0) {
+                                       break;
+                               case STAT_STATUS_NONE:
                                        chunk_printf(&msg,
                                                     "<p><div class=active2>"
                                                     "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
                                                     "Nothing has changed."
                                                     "</div>\n", uri->uri_prefix);
-                               }
-                               else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_PART) == 0) {
+                                       break;
+                               case STAT_STATUS_PART:
                                        chunk_printf(&msg,
                                                     "<p><div class=active2>"
                                                     "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
                                                     "Action partially processed.<br>"
                                                     "Some server names are probably unknown or ambiguous (duplicated names in the backend)."
                                                     "</div>\n", uri->uri_prefix);
-                               }
-                               else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_ERRP) == 0) {
+                                       break;
+                               case STAT_STATUS_ERRP:
                                        chunk_printf(&msg,
                                                     "<p><div class=active0>"
                                                     "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
@@ -2056,23 +2064,23 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
                                                     "<li>Some server names are probably unknown or ambiguous (duplicated names in the backend).</li>"
                                                     "</ul>"
                                                     "</div>\n", uri->uri_prefix);
-                               }
-                               else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_EXCD) == 0) {
+                                       break;
+                               case STAT_STATUS_EXCD:
                                        chunk_printf(&msg,
                                                     "<p><div class=active0>"
                                                     "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
                                                     "<b>Action not processed : the buffer couldn't store all the data.<br>"
                                                     "You should retry with less servers at a time.</b>"
                                                     "</div>\n", uri->uri_prefix);
-                               }
-                               else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_DENY) == 0) {
+                                       break;
+                               case STAT_STATUS_DENY:
                                        chunk_printf(&msg,
                                                     "<p><div class=active0>"
                                                     "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
                                                     "<b>Action denied.</b>"
                                                     "</div>\n", uri->uri_prefix);
-                               }
-                               else {
+                                       break;
+                               default:
                                        chunk_printf(&msg,
                                                     "<p><div class=active6>"
                                                     "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
index bf91328fe08db902fa3e28d533061ec0664d7846..3f6ec0484f35ac4999f637affaae36ba7bd7133c 100644 (file)
@@ -188,6 +188,18 @@ static const char *http_err_msgs[HTTP_ERR_SIZE] = {
 
 };
 
+/* status codes available for the stats admin page (strictly 4 chars length) */
+const char *stat_status_codes[STAT_STATUS_SIZE] = {
+       [STAT_STATUS_DENY] = "DENY",
+       [STAT_STATUS_DONE] = "DONE",
+       [STAT_STATUS_ERRP] = "ERRP",
+       [STAT_STATUS_EXCD] = "EXCD",
+       [STAT_STATUS_NONE] = "NONE",
+       [STAT_STATUS_PART] = "PART",
+       [STAT_STATUS_UNKN] = "UNKN",
+};
+
+
 /* We must put the messages here since GCC cannot initialize consts depending
  * on strlen().
  */
@@ -7132,6 +7144,7 @@ int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct pr
                return 0;
 
        memset(&si->applet.ctx.stats, 0, sizeof(si->applet.ctx.stats));
+       si->applet.ctx.stats.st_code = STAT_STATUS_INIT;
 
        /* check URI size */
        if (uri_auth->uri_len > txn->req.sl.rq.u_l)
@@ -7175,22 +7188,15 @@ int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct pr
        h = txn->req.sol + txn->req.sl.rq.u + uri_auth->uri_len;
        while (h <= txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 8) {
                if (memcmp(h, ";st=", 4) == 0) {
+                       int i;
                        h += 4;
-
-                       if (memcmp(h, STAT_STATUS_DONE, 4) == 0)
-                               si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
-                       else if (memcmp(h, STAT_STATUS_NONE, 4) == 0)
-                               si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
-                       else if (memcmp(h, STAT_STATUS_PART, 4) == 0)
-                               si->applet.ctx.stats.st_code = STAT_STATUS_PART;
-                       else if (memcmp(h, STAT_STATUS_ERRP, 4) == 0)
-                               si->applet.ctx.stats.st_code = STAT_STATUS_ERRP;
-                       else if (memcmp(h, STAT_STATUS_EXCD, 4) == 0)
-                               si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
-                       else if (memcmp(h, STAT_STATUS_DENY, 4) == 0)
-                               si->applet.ctx.stats.st_code = STAT_STATUS_DENY;
-                       else
-                               si->applet.ctx.stats.st_code = STAT_STATUS_UNKN;
+                       for (i = STAT_STATUS_INIT + 1; i < STAT_STATUS_SIZE; i++) {
+                               if (strncmp(stat_status_codes[i], h, 4) == 0) {
+                                       si->applet.ctx.stats.st_code = i;
+                                       break;
+                               }
+                       }
+                       si->applet.ctx.stats.st_code = STAT_STATUS_UNKN;
                        break;
                }
                h++;