463 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			463 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * $Id$
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								    Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Redistribution and use in source and binary forms, with or without
							 | 
						||
| 
								 | 
							
								    modification, are permitted provided that the following conditions
							 | 
						||
| 
								 | 
							
								    are met:
							 | 
						||
| 
								 | 
							
								    1. Redistributions of source code must retain the above copyright
							 | 
						||
| 
								 | 
							
								       notice, this list of conditions and the following disclaimer.
							 | 
						||
| 
								 | 
							
								    2. Redistributions in binary form must reproduce the above copyright
							 | 
						||
| 
								 | 
							
								       notice, this list of conditions and the following disclaimer in the
							 | 
						||
| 
								 | 
							
								       documentation and/or other materials provided with the distribution.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
							 | 
						||
| 
								 | 
							
								    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
							 | 
						||
| 
								 | 
							
								    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
							 | 
						||
| 
								 | 
							
								    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
							 | 
						||
| 
								 | 
							
								    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
							 | 
						||
| 
								 | 
							
								    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
							 | 
						||
| 
								 | 
							
								    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
							 | 
						||
| 
								 | 
							
								    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
							 | 
						||
| 
								 | 
							
								    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
							 | 
						||
| 
								 | 
							
								    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "mod-memc.h"
							 | 
						||
| 
								 | 
							
								#include "../lib/hawk-prv.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <libmemcached/memcached.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define __IDMAP_NODE_T_DATA  memcached_st *memc;
							 | 
						||
| 
								 | 
							
								#define __IDMAP_LIST_T_DATA  memcached_return_t rc; hawk_ooch_t errmsg[256];
							 | 
						||
| 
								 | 
							
								#define __IDMAP_LIST_T memc_list_t
							 | 
						||
| 
								 | 
							
								#define __IDMAP_NODE_T memc_node_t
							 | 
						||
| 
								 | 
							
								#define __INIT_IDMAP_LIST __init_memc_list
							 | 
						||
| 
								 | 
							
								#define __FINI_IDMAP_LIST __fini_memc_list
							 | 
						||
| 
								 | 
							
								#define __MAKE_IDMAP_NODE __new_memc_node
							 | 
						||
| 
								 | 
							
								#define __FREE_IDMAP_NODE __free_memc_node
							 | 
						||
| 
								 | 
							
								#include "../lib/idmap-imp.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct rtx_data_t
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_list_t memc_list;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								typedef struct rtx_data_t rtx_data_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ------------------------------------------------------------------------ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static memc_node_t* new_memc_node (hawk_rtx_t* rtx, memc_list_t* memc_list)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_node_t* memc_node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_node = __new_memc_node(rtx, memc_list);
							 | 
						||
| 
								 | 
							
									if (!memc_node) return HAWK_NULL;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_node->memc = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									return memc_node;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void free_memc_node (hawk_rtx_t* rtx, memc_list_t* memc_list, memc_node_t* memc_node)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (memc_node->memc != HAWK_NULL) {
							 | 
						||
| 
								 | 
							
										memcached_free (memc_node->memc);
							 | 
						||
| 
								 | 
							
										memc_node->memc = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									__free_memc_node (rtx, memc_list, memc_node);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static HAWK_INLINE memc_list_t* rtx_to_memc_list (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									hawk_rbt_pair_t* pair;
							 | 
						||
| 
								 | 
							
									rtx_data_t* data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									pair = hawk_rbt_search((hawk_rbt_t*)fi->mod->ctx, &rtx, HAWK_SIZEOF(rtx));
							 | 
						||
| 
								 | 
							
									HAWK_ASSERT (pair != HAWK_NULL);
							 | 
						||
| 
								 | 
							
									data = (rtx_data_t*)HAWK_RBT_VPTR(pair);
							 | 
						||
| 
								 | 
							
									return &data->memc_list;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void set_error_on_memc_list (hawk_rtx_t* rtx, memc_list_t* memc_list, const hawk_ooch_t* errfmt, ...)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (errfmt)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										va_list ap;
							 | 
						||
| 
								 | 
							
										va_start (ap, errfmt);
							 | 
						||
| 
								 | 
							
										hawk_rtx_vfmttooocstr (rtx, memc_list->errmsg, HAWK_COUNTOF(memc_list->errmsg), errfmt, ap);
							 | 
						||
| 
								 | 
							
										va_end (ap);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										hawk_copy_oocstr (memc_list->errmsg, HAWK_COUNTOF(memc_list->errmsg), hawk_rtx_geterrmsg(rtx));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static HAWK_INLINE memc_node_t* get_memc_list_node (memc_list_t* memc_list, hawk_int_t id)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (id < 0 || id >= memc_list->map.high || !memc_list->map.tab[id]) return HAWK_NULL;
							 | 
						||
| 
								 | 
							
									return memc_list->map.tab[id];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static memc_node_t* get_memc_list_node_with_arg (hawk_rtx_t* rtx, memc_list_t* memc_list, hawk_val_t* arg)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									hawk_int_t id;
							 | 
						||
| 
								 | 
							
									memc_node_t* memc_node;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (hawk_rtx_valtoint(rtx, arg, &id) <= -1)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										set_error_on_memc_list (rtx, memc_list, HAWK_T("illegal instance id"));
							 | 
						||
| 
								 | 
							
										return HAWK_NULL;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else if (!(memc_node = get_memc_list_node(memc_list, id)))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										set_error_on_memc_list (rtx, memc_list, HAWK_T("invalid instance id - %zd"), (hawk_oow_t)id);
							 | 
						||
| 
								 | 
							
										return HAWK_NULL;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return memc_node;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ------------------------------------------------------------------------ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fnc_new (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_list_t* memc_list;
							 | 
						||
| 
								 | 
							
									memc_node_t* memc_node = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									hawk_int_t ret = -1;
							 | 
						||
| 
								 | 
							
									hawk_val_t* retv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_list = rtx_to_memc_list(rtx, fi);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_node = new_memc_node(rtx, memc_list);
							 | 
						||
| 
								 | 
							
									if (memc_node) ret = memc_node->id;
							 | 
						||
| 
								 | 
							
									else set_error_on_memc_list (rtx, memc_list, HAWK_NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* ret may not be a statically managed number.
							 | 
						||
| 
								 | 
							
									 * error checking is required */
							 | 
						||
| 
								 | 
							
									retv = hawk_rtx_makeintval(rtx, ret);
							 | 
						||
| 
								 | 
							
									if (retv == HAWK_NULL)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (memc_node) free_memc_node (rtx, memc_list, memc_node);
							 | 
						||
| 
								 | 
							
										return -1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_rtx_setretval (rtx, retv);
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fnc_connect (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_list_t* memc_list;
							 | 
						||
| 
								 | 
							
									memc_node_t* memc_node;
							 | 
						||
| 
								 | 
							
									hawk_val_t* a0;
							 | 
						||
| 
								 | 
							
									hawk_bch_t* conf = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									hawk_oow_t conf_len = 0;
							 | 
						||
| 
								 | 
							
									int ret = -1, take_rtx_err = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_list = rtx_to_memc_list(rtx, fi);
							 | 
						||
| 
								 | 
							
									memc_node = get_memc_list_node_with_arg(rtx, memc_list, hawk_rtx_getarg(rtx, 0));
							 | 
						||
| 
								 | 
							
									if (memc_node)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										a0 = hawk_rtx_getarg(rtx, 0);
							 | 
						||
| 
								 | 
							
										if (!(conf = hawk_rtx_getvalbcstr(rtx, a0, &conf_len)))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											take_rtx_err = 1;
							 | 
						||
| 
								 | 
							
											goto done;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										memc_node->memc = memcached (conf, conf_len);
							 | 
						||
| 
								 | 
							
										if (memc_node->memc == HAWK_NULL)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											set_error_on_memc_list (rtx, memc_list, HAWK_T("unable to connect to %hs"), conf);
							 | 
						||
| 
								 | 
							
											goto done;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										ret = 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								done:
							 | 
						||
| 
								 | 
							
									if (take_rtx_err) set_error_on_memc_list (rtx, memc_list, HAWK_NULL);
							 | 
						||
| 
								 | 
							
									if (conf) hawk_rtx_freevalbcstr (rtx, a0, conf);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, ret));
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fnc_close (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_list_t* memc_list;
							 | 
						||
| 
								 | 
							
									memc_node_t* memc_node;
							 | 
						||
| 
								 | 
							
									int ret = -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_list = rtx_to_memc_list(rtx, fi);
							 | 
						||
| 
								 | 
							
									memc_node = get_memc_list_node_with_arg(rtx, memc_list, hawk_rtx_getarg(rtx, 0));
							 | 
						||
| 
								 | 
							
									if (memc_node)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										free_memc_node (rtx, memc_list, memc_node);
							 | 
						||
| 
								 | 
							
										ret = 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, ret));
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fnc_errmsg (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_list_t* memc_list;
							 | 
						||
| 
								 | 
							
									hawk_val_t* retv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_list = rtx_to_memc_list(rtx, fi);
							 | 
						||
| 
								 | 
							
									retv = hawk_rtx_makestrvalwithoocstr(rtx, memc_list->errmsg);
							 | 
						||
| 
								 | 
							
									if (!retv) return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_rtx_setretval (rtx, retv);
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fnc_get (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_list_t* memc_list;
							 | 
						||
| 
								 | 
							
									memc_node_t* memc_node;
							 | 
						||
| 
								 | 
							
									int take_rtx_err = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_val_t* a1, * a2;
							 | 
						||
| 
								 | 
							
									hawk_bch_t* key = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									hawk_bch_t* def_val = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									hawk_bch_t* rv = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									hawk_oow_t key_len = 0;
							 | 
						||
| 
								 | 
							
									hawk_oow_t def_val_len = 0;
							 | 
						||
| 
								 | 
							
									hawk_oow_t rv_len = 0;
							 | 
						||
| 
								 | 
							
									char* val = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									size_t val_len = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_list = rtx_to_memc_list(rtx, fi);
							 | 
						||
| 
								 | 
							
									memc_node = get_memc_list_node_with_arg(rtx, memc_list, hawk_rtx_getarg(rtx, 0));
							 | 
						||
| 
								 | 
							
									if (!memc_node)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										goto done;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										uint32_t flags;
							 | 
						||
| 
								 | 
							
										memcached_return_t rc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										hawk_oow_t nargs;
							 | 
						||
| 
								 | 
							
										nargs = hawk_rtx_getnargs(rtx);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										a1 = hawk_rtx_getarg(rtx, 1);
							 | 
						||
| 
								 | 
							
										if (!(key = hawk_rtx_getvalbcstr(rtx, a1, &key_len)))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											take_rtx_err = 1;
							 | 
						||
| 
								 | 
							
											goto done;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (nargs >= 3)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											a2 = hawk_rtx_getarg(rtx, 2);
							 | 
						||
| 
								 | 
							
											if (!(def_val = hawk_rtx_getvalbcstr(rtx, a2, &def_val_len)))
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												take_rtx_err = 1;
							 | 
						||
| 
								 | 
							
												goto done;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										val = memcached_get(memc_node->memc, key, key_len, &val_len, &flags, &rc);
							 | 
						||
| 
								 | 
							
										if (val == HAWK_NULL) goto done;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										rv = val;
							 | 
						||
| 
								 | 
							
										rv_len = val_len;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								done:
							 | 
						||
| 
								 | 
							
									if (rv == HAWK_NULL)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (def_val != HAWK_NULL) rv = "";
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											rv = def_val;
							 | 
						||
| 
								 | 
							
											rv_len = def_val_len;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									hawk_rtx_setretval (rtx, hawk_rtx_makestrvalwithbchars(rtx, rv, rv_len));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (take_rtx_err) set_error_on_memc_list (rtx, memc_list, HAWK_NULL);
							 | 
						||
| 
								 | 
							
									if (key) hawk_rtx_freevalbcstr (rtx, a1, key);
							 | 
						||
| 
								 | 
							
									if (def_val) hawk_rtx_freevalbcstr (rtx, a2, def_val);
							 | 
						||
| 
								 | 
							
									if (val) free(val);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fnc_set (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									memc_list_t* memc_list;
							 | 
						||
| 
								 | 
							
									memc_node_t* memc_node;
							 | 
						||
| 
								 | 
							
									int ret = -1;
							 | 
						||
| 
								 | 
							
									int take_rtx_err = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_val_t* a1, * a2, * a3, * a4;
							 | 
						||
| 
								 | 
							
									hawk_bch_t* key = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									hawk_bch_t* val = HAWK_NULL;
							 | 
						||
| 
								 | 
							
									hawk_oow_t key_len = 0;
							 | 
						||
| 
								 | 
							
									hawk_oow_t val_len = 0;
							 | 
						||
| 
								 | 
							
									hawk_int_t ttl = 0;
							 | 
						||
| 
								 | 
							
									hawk_int_t flag = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc_list = rtx_to_memc_list(rtx, fi);
							 | 
						||
| 
								 | 
							
									memc_node = get_memc_list_node_with_arg(rtx, memc_list, hawk_rtx_getarg(rtx, 0));
							 | 
						||
| 
								 | 
							
									if (!memc_node)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										goto done;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									else
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										hawk_oow_t nargs;
							 | 
						||
| 
								 | 
							
										memcached_return_t rc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										a1 = hawk_rtx_getarg(rtx, 1);
							 | 
						||
| 
								 | 
							
										a2 = hawk_rtx_getarg(rtx, 2);
							 | 
						||
| 
								 | 
							
										a3 = hawk_rtx_getarg(rtx, 3);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (!(key = hawk_rtx_getvalbcstr(rtx, a1, &key_len)) ||
							 | 
						||
| 
								 | 
							
										    !(val = hawk_rtx_getvalbcstr(rtx, a2, &val_len)) ||
							 | 
						||
| 
								 | 
							
										    (hawk_rtx_valtoint(rtx, a3, &ttl) <= -1))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											take_rtx_err = 1;
							 | 
						||
| 
								 | 
							
											goto done;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										nargs = hawk_rtx_getnargs(rtx);
							 | 
						||
| 
								 | 
							
										if (nargs >= 5) {
							 | 
						||
| 
								 | 
							
											a4 = hawk_rtx_getarg(rtx, 4);
							 | 
						||
| 
								 | 
							
											if (hawk_rtx_valtoint(rtx, a4, &flag) <= -1)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												take_rtx_err = 1;
							 | 
						||
| 
								 | 
							
												goto done;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										rc = memcached_set(memc_node->memc, key, key_len, val, val_len, ttl, flag);
							 | 
						||
| 
								 | 
							
										if (rc != MEMCACHED_SUCCESS) {
							 | 
						||
| 
								 | 
							
											goto done;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										ret = 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								done:
							 | 
						||
| 
								 | 
							
									if (take_rtx_err) set_error_on_memc_list (rtx, memc_list, HAWK_NULL);
							 | 
						||
| 
								 | 
							
									if (key) hawk_rtx_freevalbcstr (rtx, a1, key);
							 | 
						||
| 
								 | 
							
									if (val) hawk_rtx_freevalbcstr (rtx, a2, val);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, ret));
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ------------------------------------------------------------------------ */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static hawk_mod_fnc_tab_t fnctab[] =
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									/* keep this table sorted for binary search in query(). */
							 | 
						||
| 
								 | 
							
									{ HAWK_T("close"),   { { 1, 1, HAWK_NULL }, fnc_close,   0 } },
							 | 
						||
| 
								 | 
							
									{ HAWK_T("connect"), { { 1, 1, HAWK_NULL }, fnc_connect, 0 } },
							 | 
						||
| 
								 | 
							
									{ HAWK_T("errmsg"),  { { 0, 0, HAWK_NULL }, fnc_errmsg,  0 } },
							 | 
						||
| 
								 | 
							
									{ HAWK_T("get"),     { { 2, 3, HAWK_NULL }, fnc_get,     0 } },
							 | 
						||
| 
								 | 
							
									{ HAWK_T("new"),     { { 0, 0, HAWK_NULL }, fnc_new,     0 } },
							 | 
						||
| 
								 | 
							
									{ HAWK_T("set"),     { { 4, 5, HAWK_NULL }, fnc_set,     0 } },
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int query (hawk_mod_t* mod, hawk_t* hawk, const hawk_ooch_t* name, hawk_mod_sym_t* sym)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return hawk_findmodsymfnc(hawk, fnctab, HAWK_COUNTOF(fnctab), name, sym);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int init (hawk_mod_t* mod, hawk_rtx_t* rtx)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									hawk_rbt_t* rbt;
							 | 
						||
| 
								 | 
							
									rtx_data_t data, * datap;
							 | 
						||
| 
								 | 
							
									hawk_rbt_pair_t* pair;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rbt = (hawk_rbt_t*)mod->ctx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									HAWK_MEMSET (&data, 0, HAWK_SIZEOF(data));
							 | 
						||
| 
								 | 
							
									pair = hawk_rbt_insert(rbt, &rtx, HAWK_SIZEOF(rtx), &data, HAWK_SIZEOF(data));
							 | 
						||
| 
								 | 
							
									if (HAWK_UNLIKELY(!pair)) return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									datap = (rtx_data_t*)HAWK_RBT_VPTR(pair);
							 | 
						||
| 
								 | 
							
									__init_memc_list (rtx, &datap->memc_list);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void fini (hawk_mod_t* mod, hawk_rtx_t* rtx)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									hawk_rbt_t* rbt;
							 | 
						||
| 
								 | 
							
									hawk_rbt_pair_t* pair;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rbt = (hawk_rbt_t*)mod->ctx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/* garbage clean-up */
							 | 
						||
| 
								 | 
							
									pair = hawk_rbt_search(rbt, &rtx, HAWK_SIZEOF(rtx));
							 | 
						||
| 
								 | 
							
									if (pair)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										rtx_data_t* data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										data = (rtx_data_t*)HAWK_RBT_VPTR(pair);
							 | 
						||
| 
								 | 
							
										__fini_memc_list (rtx, &data->memc_list);
							 | 
						||
| 
								 | 
							
										hawk_rbt_delete (rbt, &rtx, HAWK_SIZEOF(rtx));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void unload (hawk_mod_t* mod, hawk_t* hawk)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									hawk_rbt_t* rbt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rbt = (hawk_rbt_t*)mod->ctx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									HAWK_ASSERT (HAWK_RBT_SIZE(rbt) == 0);
							 | 
						||
| 
								 | 
							
									hawk_rbt_close (rbt);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int hawk_mod_memc (hawk_mod_t* mod, hawk_t* hawk)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									hawk_rbt_t* rbt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									mod->query = query;
							 | 
						||
| 
								 | 
							
									mod->unload = unload;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									mod->init = init;
							 | 
						||
| 
								 | 
							
									mod->fini = fini;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rbt = hawk_rbt_open(hawk_getgem(hawk), 0, 1, 1);
							 | 
						||
| 
								 | 
							
									if (HAWK_UNLIKELY(!rbt)) return -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									hawk_rbt_setstyle (rbt, hawk_get_rbt_style(HAWK_RBT_STYLE_INLINE_COPIERS));
							 | 
						||
| 
								 | 
							
									mod->ctx = rbt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ------------------------------------------------------------------------ */
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								BEGIN {
							 | 
						||
| 
								 | 
							
									conn = memc::new();
							 | 
						||
| 
								 | 
							
									if (memc::connect("--SERVER=localhost") <= -1)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										print "connect error -", memc::errmsg();
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									rc = memc::set(conn, "key", "val", 900);
							 | 
						||
| 
								 | 
							
									if (rc <= -1) {
							 | 
						||
| 
								 | 
							
										print "store result error - ", memc::errmsg();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									val = memc::get(conn, "key");            print val;
							 | 
						||
| 
								 | 
							
									val = memc::get(conn, "key", "default"); print val;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									memc::close(conn);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								*/
							 |