rrd_graph
fucntion with the arguments you usually give rrd on the command line. So, I need to create a temporary file for this. Luckily enough, nginx seems to have a nice function handy for that:ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean, ngx_uint_t access)
- The
access
argument is simple: it's what you would use as argument tochmod
the temporary file. - The
clean
argument tells nginx whether it should clean the file when it does not need it anymore (which is usually at the end of the request). Interestingly enough the cleanup mechanism relies on the pool-cleanup feature and thepool
argument. So, the cleanup could happen pretty much at any time you see fit provided you hand over the rightpool
persistent
seems to be atrick by which a file becomes effectively invisible to everybody else but its creator if this creator callsunlink
just after callingopen
withO_CREAT
ngx_path_t
is probably some kind of path but I actually got a headache trying to figure out how to create angx_path_t
. So, instead of trying to figure it out, I decided to use thengx_conf_set_path_slot
function that lets you configure a path in a directive (the brand newrrd_image_temp_path
directive in my case). I love it when everything falls in place...
While I was at it, I decided to review my good old
rrd
configuration directive. So far, it had been relying on ngx_conf_set_str
to handle the string that indicates where the rrd db is. As a result the object stored in the ngx_http_rrd_conf_loc_t
is a ngx_str_t
. Unfortunately, most of the time, I need this object as a C-style (null terminated) string to call the rrd functions. Therefore, I decided to drop using ngx_conf_str_t
and to perform the "conversion" to c-style once and for all at configuration time.After that I tried to put together the new directive. And, once again, I tried to be smarter than I should have. Once again, it backfired... :( Here is the story...
The new directive had no reason to be limited to the location scope. It could as well be in the server or even the main scope. So, I decided to configure the corresponding
ngx_command_t
accordingly:{ ngx_string("rrd_image_temp_path"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, ngx_conf_set_path_slot,Note, that pretty much summarizes all I said so far: directive is rrd_image_temp_path; it is allowed at main, server and location scopes; it takes 1 to 4 arguments which are handled by
ngx_conf_set_path_slot
(what I call the "ngx_path black magic").And then, I had to figure out what should be the other fields of the structure:
ngx_uint_t conf; ngx_uint_t offset; void *post;
post
was easy: no post-processing, so useNULL
.offset
was the offset where the variable would be in my configuration object. So something like:offsetof(ngx_http_rrd_loc_conf_t, rrd_image_temp_path)
.conf
was a bit trickier and got me wondering. As the directive could be up to the main scope, I set it toNGX_HTTP_MAIN_CONF_OFFSET
. And as Yoda would put it "That is why you fail"...
But before realising I had failed, I wrote my nice little configuration merging function:
static char * ngx_http_rrd_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_rrd_loc_conf_t* plcf = parent; ngx_http_rrd_loc_conf_t* clcf = child; if (ngx_conf_merge_path_value(cf, &clcf->rrd_image_temp_path, plcf->rrd_image_temp_path, &ngx_http_rrd_temp_path) != NGX_OK) { return NGX_CONF_ERROR; } return NGX_CONF_OK; }Pretty easy as long as you use the "out-of-the-box" tools of nginx like
ngx_conf_merge_path_value
.Except that after getting the thing to compile, nothing was working. My nginx server would not even start. And after quite a bit of research I figured the culprit was the
conf
. What nginx expects here has absolutely nothing to do with where the directive is allowed (this is handled in one place only: the type
field of ngx_command_t
) it has to do with where the data is stored: the location configuration structure, the server configuration structure or the main configuration structure. In our example, as we want to be able to set this to the location in certain situations, the data must be in the location configuration structure. So, the right value is NGX_HTTP_LOC_CONF_OFFSET
. So, with conf
and offset
, nginx is able to figure out where exactly it should put the data it read from the configuration file.That's all folks.
No comments:
Post a Comment