diff --git a/ROADMAP b/ROADMAP index 6faa0e37f..b17160ccf 100644 --- a/ROADMAP +++ b/ROADMAP @@ -1,4 +1,4 @@ -'+' = done, '-' = todo +'+' = done, '-' = todo, '*' = done except doc 1.2.12 : + weighted RR/SH @@ -8,7 +8,15 @@ + queueing 1.2.14 : - - HTML status page + * HTML status page + + stats enable + stats uri /?stats + stats realm w.ods.org\ statistics + stats auth user1:pass1 + stats auth user2:pass2 + stats auth user3:pass3 + stats scope | '.' - separate timeout controls @@ -25,6 +33,8 @@ srv->effective_maxconn = max(srv->maxconn * px->nbsess / px->maxconn, srv->minconn) + - allow server-less proxies (for stats) + 1.3 : - handle half-closed connections better (cli/srv would not distinguish DATA/SHUTR/SHUTW, it would be a session flag which would tell shutr/shutw). diff --git a/haproxy.c b/haproxy.c index f18ab6b98..e90aae79b 100644 --- a/haproxy.c +++ b/haproxy.c @@ -442,6 +442,10 @@ char *ultoa(unsigned long n) { #define DATA_SRC_NONE 0 #define DATA_SRC_STATS 1 +/* data transmission states for the responses */ +#define DATA_ST_INIT 0 +#define DATA_ST_DATA 1 + /* different possible states for the client side */ #define CL_STHEADERS 0 #define CL_STDATA 1 @@ -641,11 +645,13 @@ struct session { int status; /* HTTP status from the server, negative if from proxy */ long long bytes; /* number of bytes transferred from the server */ } logs; - int data_source; /* where to get the data we generate ourselves */ + short int data_source; /* where to get the data we generate ourselves */ + short int data_state; /* where to get the data we generate ourselves */ union { struct { struct proxy *px; struct server *sv; + short px_st, sv_st; /* DATA_ST_INIT or DATA_ST_DATA */ } stats; } data_ctx; unsigned int uniq_id; /* unique ID used for the traces */ @@ -2981,6 +2987,7 @@ int buffer_realign(struct buffer *buf) { /* writes bytes from message to buffer . Returns 0 in case of * success, or the number of bytes available otherwise. + * FIXME-20060521: handle unaligned data. */ int buffer_write(struct buffer *buf, const char *msg, int len) { int max; @@ -3042,19 +3049,21 @@ int produce_content(struct session *s) { struct proxy *px; struct server *sv; int msglen; - unsigned int up; - int failed_checks, down_trans; if (s->data_source == DATA_SRC_NONE) { s->flags &= ~SN_SELF_GEN; return 1; } else if (s->data_source == DATA_SRC_STATS) { - if (s->data_ctx.stats.px == NULL) { /* initialized to NULL at session creation */ - /* the proxy was not known, the function had not been called yet */ - + msglen = 0; + + if (s->data_state == DATA_ST_INIT) { /* the function had not been called yet */ + unsigned int up; + s->flags |= SN_SELF_GEN; // more data will follow - msglen = sprintf(trash, + + /* send the start of the HTTP response */ + msglen += snprintf(trash + msglen, sizeof(trash) - msglen, "HTTP/1.0 200 OK\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" @@ -3062,13 +3071,15 @@ int produce_content(struct session *s) { s->logs.status = 200; client_retnclose(s, msglen, trash); // send the start of the response. + msglen = 0; + if (!(s->flags & SN_ERR_MASK)) // this is not really an error but it is s->flags |= SN_ERR_PRXCOND; // to mark that it comes from the proxy if (!(s->flags & SN_FINST_MASK)) s->flags |= SN_FINST_R; /* WARNING! This must fit in the first buffer !!! */ - msglen = snprintf(trash, sizeof(trash), + msglen += snprintf(trash + msglen, sizeof(trash) - msglen, "Statistics Report for " PRODUCT_NAME "\n" "\n" "