Thursday, February 17, 2011

Day 22 - rrd directive, post argument handler, ngx_str_t to ngx_buf_t, patch day

A lot of different things today. So, I'll try to be concise and to the point with each.

I finally stabilised the specs for the configuration of my module. I already told you the HttpRRDModule will have to be activated with a directive. This directive will be valid only at the location level and it will take one mandatory argument: the name of the RRD database. This is all nice and good and can pretty much translate into the following ngx_command_t:
{ ngx_string("rrd"),
NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_rrd_module_conf_t, db_name),
&ngx_http_rrd_post},
As you can see, since I'm a lazy guy I let nginx do most of the job. That includes parsing the directive argument and setting it into my structure:
typedef struct {
ngx_str_t db_name; /* Name of rrd database. */
} ngx_http_rrd_module_conf_t;
Now, I still want to be able to set the handler for requests and this is not done by ngx_conf_set_str_slot as you probably guessed. However, nginx offers a mechanism to do it. And this mechanism is the post field of ngx_command_t. But don't mistake the void* to be the pointer to the function that will do the "post-configuration job". Or you will end-up exactly where I ended: crash of nginx at configuration load. This is not very forgiving. The trick here is to use as post the ngx_conf_post_t structure:
static char *ngx_http_rrd_post_command(ngx_conf_t *cf, void *data, void *conf);
[...]
static ngx_conf_post_t ngx_http_rrd_post = {
ngx_http_rrd_post_command
};
I'm sure there is a good reason for post being of type void * instead of ngx_conf_post_t * but I have no clue what this reason might be.


Now that I have my configuration read and processed, I wanted to send a response with only a fixed text saying "everything is fine". This is pretty much the Echo module I'm rewriting...only crappier. As soon as you want to send a response, you have to go through a ngx_chain_t of ngx_buf_t. At this point I am "there must be a way to create a buffer from a ngx_str_t !!!". Except that I spent a lot of time looking for it and couldn't find it. So, I wrote one myself:
/*
* Helper function to allocate a buffer from a string.
*/
ngx_buf_t * ngx_http_rrd_create_buf_from_str(ngx_pool_t *pool, ngx_str_t *s)
{
ngx_buf_t *buf;
buf = ngx_calloc_buf(pool);
if (NULL == buf) {
return NULL;
}
buf->start = s->data;
buf->end = s->data + s->len;
buf->pos = buf->start;
buf->last = buf->end;
buf->memory = 1;
return buf;
}
Feel free to use it. If anyone cares, this is officially public-domain.

I think of the license because of something that happened on the mailing-list. Maxim Dounim posted no less than 31 patches against 0.9.4 (what is considered to be the HEAD). And someone asked what was the license. The author answered "BSD, like the rest of nginx". A lot of the patches are backport of patches already submitted against 0.8.X. A few interesting things:
  • Igor does not seem to be in a hurry to integrate other people patches.
  • One of the patches allow to reuse keep-alive connections when nginx needs more connections to handle the load. Pretty nifty and might be useful.
  • Maxim rocks

No comments:

Post a Comment