Пример #1
0
void temperhum_rrd_update(char *fname, time_t tv_sec, struct sht1x_readings readings) {
	char update[4096];
	char buf[512];
	const char *args[1];

	args[0] = update;
	snprintf(update, 4096, "%llu", (unsigned long long)tv_sec);

	if (isnan(readings.temperature_celsius))
		strcat(update, ":U");
	else {
		snprintf(buf, 512, ":%.2f", readings.temperature_celsius);
		strcat(update, buf);
	}

	if (isnan(readings.relative_humidity))
		strcat(update, ":U");
	else {
		snprintf(buf, 512, ":%.2f", readings.relative_humidity);
		strcat(update, buf);
	}

	if (isnan(readings.dew_point))
		strcat(update, ":U");
	else {
		snprintf(buf, 512, ":%.2f", readings.dew_point);
		strcat(update, buf);
	}

	rrd_clear_error();
	if (rrd_update_r(fname, "tc:rh:dp", 1, args) != 0)
		fprintf(stderr, "%s: (%s) %s\n", fname, args[0], rrd_get_error());
}
/*
 *  Called when the full body has been received. Even if the body is sent in
 *  multiple chunks, this will be called only once when everything has
 *  been received.
 */
void ngx_http_rrd_body_received(ngx_http_request_t *r)
{
    ngx_log_t *log = r->connection->log;
    ngx_chain_t *body_chain = r->request_body->bufs;
    /* Use the content length as a max for our value. */
    u_char* copy_idx;
    /*  In theory I should check for the size of the body to avoid loading
     * too much stuff in memory. However this is already handled by nginx
     * client_max_body_size. If the admin thinks it's taking too much memory
     * he/she should use client_max_body_size.
     */
    u_char* rrd_value = copy_idx =
            ngx_palloc(r->pool, r->headers_in.content_length_n);
    if (NULL == rrd_value) {
        ngx_log_error(NGX_LOG_ALERT, log, 0,
                       "Alloc problem @ngx_http_rrd_body_received/1");
        return ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
    }
    u_char* p;
    /* TODO: rewrite this to first READ in mem, then look for = and urldecode*/
    ngx_int_t looking_for_eq = 1;
    /* Needed for pipelined requests in HTTP/1.1 which can all be in one buf. */
    ngx_int_t left_in_contentlength = r->headers_in.content_length_n;
    do {
        ngx_buf_t *temp_buf;
        if (body_chain->buf->in_file) {
            ngx_buf_t * file_buf = body_chain->buf;
            /* Read it first in mem. This is unfortunately blocking.
             * TODO : non-blocking. HttpUploadModule ?
             */
            temp_buf = ngx_create_temp_buf(r->pool, ngx_buf_size(file_buf));
            if (NULL == temp_buf) {
                ngx_log_error(NGX_LOG_ALERT, log, 0,
                               "Alloc problem @ngx_http_rrd_body_received/2");
                return ngx_http_finalize_request(r,
                                         NGX_HTTP_INTERNAL_SERVER_ERROR);
            }
            ssize_t read_n;
            read_n = ngx_read_file(file_buf->file, temp_buf->start,
                                   ngx_buf_size(file_buf), 0);
            if (read_n < 0) {
                /* Problem already logged by read_file. */
                return ngx_http_finalize_request(r,
                                         NGX_HTTP_INTERNAL_SERVER_ERROR);
            } else {
                temp_buf->last = temp_buf->start + read_n;
            }
        } else {
            temp_buf = body_chain->buf;
        }
        p = temp_buf->start;
        while (p!=temp_buf->last && looking_for_eq && left_in_contentlength>0) {
            if ('=' == *(p++)) {
                looking_for_eq = 0;
            }
            left_in_contentlength--;
        }
        if (!looking_for_eq) {
            u_char *dst = copy_idx;
            u_char *src = p;
            /*
             *   This won't work if buffer boundary is in the middle of a
             *  percent-encoded string (which is unlikely to happen I would
             *  say. Should try to unit test this situation.
             */
            /*  We'll copy only what's left in buffer or what's left in
             * content-length.
             */
            size_t size_to_copy;
            if (left_in_contentlength < temp_buf->last - p) {
                size_to_copy = left_in_contentlength;
            } else {
                size_to_copy = temp_buf->last - p;
            }
            ngx_unescape_uri(&dst, &src, size_to_copy, 0);
            left_in_contentlength -= size_to_copy;
            copy_idx = dst;
        }
        body_chain = body_chain->next;
    } while (NULL != body_chain);
    *copy_idx = '\x0';

    ngx_http_rrd_loc_conf_t *rrd_conf;
    rrd_conf = ngx_http_get_module_loc_conf(r, ngx_http_rrd_module);

    int rrd_rc;
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, log, 0,
                  "rrd_update_r (%s, NULL, 1, %s)", rrd_conf->db_name_cstyle,
                  rrd_value);
    rrd_clear_error();
    rrd_rc = rrd_update_r(rrd_conf->db_name_cstyle, NULL,
                          1, (const char **)&rrd_value);
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, log, 0,
                  "rrd_update_r returned: %d", rrd_rc);
    ngx_int_t rc;
    if (rrd_rc < 0) {
        char * rrd_err = rrd_get_error();
        ngx_log_error(NGX_LOG_ALERT, log, 0,
                       "Problem on rrd_update_r: %s", rrd_err);
        rc = ngx_http_rrd_outprintf(r, NGX_HTTP_INTERNAL_SERVER_ERROR,
                       "Problem (%s) updating %s with %s.",
                       rrd_err, rrd_conf->db_name_cstyle, &rrd_value);
    } else {
        rc = ngx_http_rrd_outprintf(r, NGX_HTTP_OK,
                       "Updated %s. You make the rock-n-roll go round, Robin.",
                       rrd_conf->db_name_cstyle);
    }
    ngx_http_finalize_request(r, rc);
}