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); }