Skip to content

Commit

Permalink
Initial Version [alpha]
Browse files Browse the repository at this point in the history
  • Loading branch information
Reetesh Ranjan committed Dec 5, 2013
1 parent b3b503a commit 8f6f3d7
Show file tree
Hide file tree
Showing 10 changed files with 2,475 additions and 4 deletions.
66 changes: 66 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
Name

nginx-sphinx-module - Nginx upstream module for Sphinx 2.0 search daemon

*This module is not distributed with the Nginx source.* See the installation
instructions.

Status

Alpha

Version

0.1

Synopsis

# Search
# /search?&offset=0&nres=20&match=all
# &ranker=proxbm25&rankexpr=
# &sort=relevance&sortby=myattr
# &keywords=Anna+Hazare
# &index=myidx
# &filters=a1,in,range,10,20;a2,ex,range,10,20;a3,in,frange,10.00,20.00
# &group=day,attr,@group desc,attr2
# &maxres=1000
# &geo=latattr,lonattr,10.00,10.00
# &idxweights=myidx:50;othidx:10
# &fldweights=content:100;title:0
# &format=json
location /search {
set_unescape_uri $sphinx2_command "search";
set_unescape_uri $sphx_offset $arg_offset;
set_unescape_uri $sphx_numresults $arg_nres;
set_unescape_uri $sphx_matchmode $arg_match;
set_unescape_uri $sphx_ranker $arg_ranker;
set_unescape_uri $sphx_rankexpr $arg_rankexpr;
set_unescape_uri $sphx_sortmode $arg_sort;
set_unescape_uri $sphx_sortby $arg_sortby;
set_unescape_uri $sphx_keywords $arg_keywords;
set_unescape_uri $sphx_index $arg_index;
set_unescape_uri $sphx_filters $arg_filters;
set_unescape_uri $sphx_group $arg_group;
set_unescape_uri $sphx_maxmatches $arg_maxres;
set_unescape_uri $sphx_geo $arg_geo;
set_unescape_uri $sphx_indexweights $arg_idxweights;
set_unescape_uri $sphx_fieldweights $arg_fldweights;
set_unescape_uri $sphx_outputtype $arg_format;
set_unescape_uri $sphx_docid "0";
sphinx2_pass 127.0.0.1:9312;
}

Description

This is an Nginx upstream module that makes nginx talk to a Sphinx
(<http://sphinxsearch.com/>) 2.x server in a non-blocking way.

Following features are supported as of now.
1 Searching

This module supports 3 output formats - XML, JSON and Raw. The URL's
outputformat query parameter can be used to specify the desired one.

Limitations

<TODO>
4 changes: 0 additions & 4 deletions README.md

This file was deleted.

7 changes: 7 additions & 0 deletions config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ngx_addon_name=ngx_http_sphinx2_module

HTTP_MODULES="$HTTP_MODULES ngx_http_sphinx2_module"

NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ngx_http_sphinx2_args_parser.h $ngx_addon_dir/src/ngx_http_sphinx2_stream.h $ngx_addon_dir/src/ngx_http_sphinx2_sphx.h"

NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_sphinx2_args_parser.c $ngx_addon_dir/src/ngx_http_sphinx2_stream.c $ngx_addon_dir/src/ngx_http_sphinx2_sphx.c $ngx_addon_dir/src/ngx_http_sphinx2_module.c"
265 changes: 265 additions & 0 deletions src/ngx_http_sphinx2_args_parser.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
/*
* Sphinx upstream module URI query params parsing
*/

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
#include <assert.h>
#include "ngx_http_sphinx2_args_parser.h"

/* FUNCTION DEFINITIONS */

/* register the input, hints and delimiter to create a parsing ctx */
ngx_int_t
sphx2_arg_parse_register(
sphx2_arg_parse_ctx_t * ctxt,
ngx_pool_t * pool,
char * input,
sphx2_arg_parse_hint_t * hints,
const char * delimiter)
{
ctxt->input = input;
ctxt->hints = hints;
ctxt->delimiter = delimiter;
ctxt->curr = NULL;
ctxt->num_tokens = 0;
ctxt->pool = pool;

return NGX_OK;
}

/* register current 'token' of a ctx to another to parse it further */
ngx_int_t
sphx2_arg_parse_register_child(
sphx2_arg_parse_ctx_t * to,
sphx2_arg_parse_ctx_t * from,
ngx_pool_t * pool,
sphx2_arg_parse_hint_t * hints,
const char * delimiter)
{
assert(NULL != from->curr);

return sphx2_arg_parse_register(to, pool, from->curr, hints, delimiter);
}

/* take one tokenizing step, so curr and input pointers are modified */
ngx_int_t
sphx2_arg_step(sphx2_arg_parse_ctx_t * ctxt)
{
if(NULL == (ctxt->curr = strsep(&ctxt->input, ctxt->delimiter))) {
return NGX_ERROR;
}

++ctxt->num_tokens;

return NGX_OK;
}

/* get a string arg - internally does a 'step' and also a check using
* the hints if available
*/
ngx_str_t*
sphx2_arg_parse_get_str_arg(sphx2_arg_parse_ctx_t * ctxt)
{
ngx_str_t * str;

if(NULL != ctxt->hints &&
SPHX2_ARG_TYPE_STRING !=
ctxt->hints[ctxt->num_tokens].param_type)
{
return(NULL);
}

if(NGX_ERROR == sphx2_arg_step(ctxt))
return (NULL);

if(NULL == (str = ngx_palloc(ctxt->pool, sizeof(ngx_str_t)))) {
return(NULL);
}

str->len = strlen(ctxt->curr)+1;

if(NULL == (str->data = ngx_palloc(ctxt->pool, str->len))) {
return(NULL);
}

memcpy(str->data, ctxt->curr, str->len);

return(str);
}

/* get an integer arg - internally does a 'step' and also a check using
* the hints if available
*/
uint32_t
sphx2_arg_parse_get_int_arg(sphx2_arg_parse_ctx_t * ctxt)
{
if(NULL != ctxt->hints &&
SPHX2_ARG_TYPE_INTEGER !=
ctxt->hints[ctxt->num_tokens].param_type)
{
return(NGX_ERROR);
}

if(NGX_ERROR == sphx2_arg_step(ctxt))
return (NGX_ERROR);

return(atoi(ctxt->curr));
}

/* get an int64 arg - internally does a 'step' and also a check using
* the hints if available
*/
uint64_t
sphx2_arg_parse_get_int64_arg(sphx2_arg_parse_ctx_t * ctxt)
{
if(NULL != ctxt->hints &&
SPHX2_ARG_TYPE_INTEGER64 !=
ctxt->hints[ctxt->num_tokens].param_type)
{
return(NGX_ERROR);
}

if(NGX_ERROR == sphx2_arg_step(ctxt))
return (NGX_ERROR);

return(strtoll(ctxt->curr, NULL, 10));
}

/* get a float arg - internally does a 'step' and also a check using
* the hints if available
*/
float
sphx2_arg_parse_get_float_arg(sphx2_arg_parse_ctx_t * ctxt)
{
if(NULL != ctxt->hints &&
SPHX2_ARG_TYPE_FLOAT !=
ctxt->hints[ctxt->num_tokens].param_type)
{
return((float)NGX_ERROR);
}

if(NGX_ERROR == sphx2_arg_step(ctxt))
return ((float)NGX_ERROR);

return(atof(ctxt->curr));
}

/* get an enum arg - internally does a 'step' and also a check using
* the hints if available. the matching str-arr if specified overrides
* the hints (if specified). one of the arg here or hint must be
* available.
*/
int32_t
sphx2_arg_parse_get_enum_arg(
sphx2_arg_parse_ctx_t * ctxt,
const char * str_arr[],
size_t sz_str_arr)
{
size_t i;

if(NULL != ctxt->hints &&
SPHX2_ARG_TYPE_ENUM !=
ctxt->hints[ctxt->num_tokens].param_type)
{
return(NGX_ERROR);
}

assert(!(NULL == str_arr && NULL == ctxt->hints));

if(NULL == str_arr) {
str_arr = ctxt->hints[ctxt->num_tokens].str_arr;
sz_str_arr = ctxt->hints[ctxt->num_tokens].sz_str_arr;
}

if(NGX_ERROR == sphx2_arg_step(ctxt))
return (NGX_ERROR);

for(i = 0; i < sz_str_arr; ++i) {
if(!strncmp(ctxt->curr, str_arr[i], strlen(str_arr[i]))) {
return (i);
}
}

return(NGX_ERROR);
}

/* parse the whole input using the hints and copy the results in the
* order specified by hints array into the target pointer arg assuming
* it is a struct pointer with elements of types specified in hints
* occurring in that order
*/
ngx_int_t
sphx2_arg_parse_whole_using_hints(
sphx2_arg_parse_ctx_t * ctxt,
void * ptr)
{
#define APPEND_4_BYTES(p, v, a) \
do { \
memcpy(p, v, sizeof(uint32_t)); \
p = (void*)((uint64_t)p + sizeof(uint32_t)); \
a = 1 - a; \
} while(0)

#define APPEND_8_BYTES(p, v, a) \
do { \
if(0==a) { p = (void*)((uint64_t)p + sizeof(uint32_t)); a = 1;}; \
memcpy(p, v, sizeof(uint64_t)); \
p = (void*)((uint64_t)p + sizeof(uint64_t)); \
} while(0)

size_t i = 0;
int32_t is_ptr_aligned = 1;
union { uint32_t i; uint64_t i64; float f; ngx_str_t* s; int32_t e; } v;

assert(NULL != ctxt->hints);

while(SPHX2_ARG_TYPE_NONE != ctxt->hints[i].param_type) {

switch(ctxt->hints[i].param_type) {
case SPHX2_ARG_TYPE_INTEGER:
if((uint32_t)NGX_ERROR == (v.i = sphx2_arg_parse_get_int_arg(ctxt)))
{
return(NGX_ERROR);
}
APPEND_4_BYTES(ptr, &v.i, is_ptr_aligned);
break;
case SPHX2_ARG_TYPE_INTEGER64:
if((uint64_t)NGX_ERROR == (v.i64 = sphx2_arg_parse_get_int64_arg(ctxt)))
{
return(NGX_ERROR);
}
APPEND_8_BYTES(ptr, &v.i64, is_ptr_aligned);
break;
case SPHX2_ARG_TYPE_FLOAT:
if((float)NGX_ERROR == (v.f = sphx2_arg_parse_get_float_arg(ctxt)))
{
return(NGX_ERROR);
}
APPEND_4_BYTES(ptr, &v.i, is_ptr_aligned);
break;
case SPHX2_ARG_TYPE_STRING:
if(NULL == (v.s = sphx2_arg_parse_get_str_arg(ctxt)))
{
return(NGX_ERROR);
}
APPEND_8_BYTES(ptr, &v.s, is_ptr_aligned);
break;
case SPHX2_ARG_TYPE_ENUM:
if((int32_t)NGX_ERROR == (v.e = sphx2_arg_parse_get_enum_arg(ctxt,
ctxt->hints[i].str_arr, ctxt->hints[i].sz_str_arr)))
{
return(NGX_ERROR);
}
APPEND_4_BYTES(ptr, &v.e, is_ptr_aligned);
break;
default:
assert(0);
}

++i;
}

return (NGX_OK);
}
Loading

0 comments on commit 8f6f3d7

Please sign in to comment.