예제 #1
0
static ssize_t chm_imp_configure  (mphf_t *mphf, request_t *config){ // {{{
	ssize_t                ret;
	chm_imp_t             *data              = (chm_imp_t *)&mphf->data;
	
	data->nelements_min  = CAPACITY_MIN_DEFAULT;
	data->nelements_step = CAPACITY_STEP_DEFAULT;
	data->nelements_mul  = CAPACITY_MUL_DEFAULT;
	data->readonly       = 0;
	
	hash_data_get(ret, TYPE_UINTT,  data->nelements_min,  config, HK(nelements_min));
	hash_data_get(ret, TYPE_UINTT,  data->nelements_step, config, HK(nelements_step));
	hash_data_get(ret, TYPE_UINTT,  data->nelements_mul,  config, HK(nelements_mul));
	hash_data_get(ret, TYPE_UINTT,  data->bt_value,       config, HK(value_size));
	hash_data_get(ret, TYPE_UINTT,  data->readonly,       config, HK(readonly));       // run in read-only mode
	
	if(data->bt_value > sizeof(uintmax_t))
		return error("value_size is too big");
	
	hash_holder_consume(ret, data->be_v, config, HK(data_v)); if(ret != 0) data->readonly = 1;
	hash_holder_consume(ret, data->be_e, config, HK(data_e)); if(ret != 0) data->readonly = 1;
	hash_holder_consume(ret, data->be_g, config, HK(data_g));
	if(ret != 0)
		return error("data chm_imp parameter data_g invalid");
	
	return 0;
} // }}}
예제 #2
0
파일: tcp.c 프로젝트: allisonmobley/frozen
static int tcp_configure(machine_t *machine, hash_t *config){ // {{{
	ssize_t                ret;
	tcp_userdata          *userdata          = (tcp_userdata *)machine->userdata;
	
	hash_data_convert(ret, TYPE_STRINGT, userdata->tcp_addr, config, HK(addr));
	hash_data_get    (ret, TYPE_UINTT,   userdata->tcp_port, config, HK(port));
	hash_data_get    (ret, TYPE_HASHT,   userdata->machine,  config, HK(machine));
	
	tcp_control_start(machine);
	return 0;
} // }}}
예제 #3
0
파일: murmur.c 프로젝트: samuell/frozen
static ssize_t murmur_configure(machine_t *machine, hash_t *config){ // {{{
	ssize_t                ret;
	murmur_userdata       *userdata          = (murmur_userdata *)machine->userdata;
	
	hash_data_get(ret, TYPE_HASHKEYT, userdata->input,    config, HK(input));
	hash_data_get(ret, TYPE_HASHKEYT, userdata->output,   config, HK(output));
	hash_data_get(ret, TYPE_UINTT,    userdata->fatal,    config, HK(fatal));
	
	userdata->fatal   = ( userdata->fatal == 0 ) ? 0 : 1;
	return 0;
} // }}}
예제 #4
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     action_write_to_fast(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	data_t                *r_buffer;
	data_t                *r_size;
	uintmax_t              offset            = 0;
	uintmax_t              size              = ~0;
	
	hash_data_get(ret, TYPE_UINTT, offset, request, HK(offset));
	
	if( (r_size   = hash_data_find(request, HK(size))) != NULL){
		data_get(ret, TYPE_UINTT, size, r_size);
	}
	
	if( (r_buffer = hash_data_find(request, HK(buffer))) == NULL)
		return -EINVAL;
	
	data_t                 d_slice    = DATA_SLICET(userdata, offset, size); // FIXME
	fastcall_convert_to    r_convert = { { 5, ACTION_CONVERT_TO }, &d_slice, FORMAT(native) };
	
	ret = data_query(r_buffer, &r_convert);
	
	fastcall_write         r_write           = { { 5, ACTION_WRITE }, 0, &r_convert.transfered, sizeof(r_convert.transfered) };
	if(r_size)
		data_query(r_size, &r_write);
	
	return ret;
} // }}}
예제 #5
0
static ssize_t data_length_t_convert_from(data_t *dst, fastcall_convert_from *fargs){ // {{{
	ssize_t                ret;
	length_t              *fdata;
	
	if(dst->ptr != NULL)
		return -EINVAL;
	
	switch(fargs->format){
		case FORMAT(hash):;
			hash_t                *config;
			
			data_get(ret, TYPE_HASHT, config, fargs->src);
			if(ret != 0)
				return ret;
			
			if( (fdata = malloc(sizeof(length_t))) == NULL)
				return -ENOMEM;
			
			hash_holder_consume(ret, fdata->data, config, HK(data));
			if(ret != 0){
				free(fdata);
				return -EINVAL;
			}
			
			fdata->format = FORMAT(clean);
			hash_data_get(ret, TYPE_FORMATT, fdata->format, config, HK(format));
			
			dst->ptr = fdata;
			return 0;
			
		default:
			break;
	}
	return -ENOSYS;
} // }}}
예제 #6
0
파일: main.c 프로젝트: allisonmobley/frozen
static int null_configure(machine_t *machine, config_t *config){ // {{{
	ssize_t                ret;
	null_userdata         *userdata          = (null_userdata *)machine->userdata;
	
	hash_data_get(ret, TYPE_UINTT, userdata->testparam, config, HK(test));
	return 0;
} // }}}
예제 #7
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     action_crud_to_fast(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	action_t               action;
	data_t                *key;
	data_t                *value;
	
	hash_data_get(ret, TYPE_ACTIONT, action, request, HK(action));
	if(ret != 0)
		return ret;
	
	key   = hash_data_find(request, HK(key));
	value = hash_data_find(request, HK(value));
	
	if(key){
		data_realholder(ret, key, key);
		if(ret < 0)
			return ret;
	}
	if(value){
		data_realholder(ret, value, value);
		if(ret < 0)
			return ret;
	}
	
	fastcall_crud fargs = { { 4, action }, key, value };
	ret = callback(userdata, &fargs);
	
	return ret;
} // }}}
예제 #8
0
static int implode_configure(machine_t *machine, hash_t *config){ // {{{
	ssize_t                ret;
	implode_userdata      *userdata          = (implode_userdata *)machine->userdata;
	
	hash_data_get(ret, TYPE_HASHKEYT, userdata->buffer,        config, HK(buffer));
	return 0;
} // }}}
예제 #9
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     action_resize_to_fast(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	fastcall_resize        fargs             = { { 4, ACTION_RESIZE } };
	
	hash_data_get(ret, TYPE_UINTT, fargs.length, request, HK(size));
	
	return callback(userdata, &fargs);
} // }}}
예제 #10
0
파일: try.c 프로젝트: allisonmobley/frozen
static int try_configure(machine_t *machine, config_t *config){ // {{{
	ssize_t                ret;
	try_userdata          *userdata          = (try_userdata *)machine->userdata;
	
	hash_data_get(ret, TYPE_HASHKEYT, userdata->request,     config, HK(request));
	if(ret == 0){
		userdata->request_out = userdata->request;
	}
	hash_data_get(ret, TYPE_HASHKEYT, userdata->request_out, config, HK(request_out));
	hash_data_get(ret, TYPE_HASHKEYT, userdata->return_to,   config, HK(return_to));
	
	hash_holder_consume(ret, userdata->machine, config, HK(shop));
	if(ret != 0)
		return error("shop parameter not supplied");
	
	return 0;
} // }}}
예제 #11
0
static int debug_configure(machine_t *machine, hash_t *config){ // {{{
	ssize_t                ret;
	uintmax_t              cfg_showdump      = 1;
	uintmax_t              cfg_before        = 1;
	uintmax_t              cfg_after         = 0;
	debug_userdata        *userdata          = (debug_userdata *)machine->userdata;
	
	hash_data_get(ret, TYPE_UINTT, cfg_showdump, config, HK(verbose));
	hash_data_get(ret, TYPE_UINTT, cfg_before,   config, HK(before));
	hash_data_get(ret, TYPE_UINTT, cfg_after,    config, HK(after));
	
	userdata->flags |= (cfg_before != 0) ? DEBUG_BEFORE : 0;
	userdata->flags |= (cfg_after  != 0) ? DEBUG_AFTER  : 0;
	userdata->show_dump = cfg_showdump;
	
	return 0;
} // }}}
예제 #12
0
파일: structs.c 프로젝트: samuell/frozen
static ssize_t struct_configure(machine_t *machine, hash_t *config){ // {{{
	ssize_t                ret;
	struct_userdata       *userdata      = (struct_userdata *)machine->userdata;
	
	hash_data_consume(ret, TYPE_HASHT,    userdata->structure,  config, HK(structure));
	hash_data_get    (ret, TYPE_HASHKEYT, userdata->buffer,     config, HK(buffer));
	hash_data_get    (ret, TYPE_HASHKEYT, userdata->key_values, config, HK(values));
	hash_data_get    (ret, TYPE_HASHKEYT, userdata->size,       config, HK(size));
	hash_data_get    (ret, TYPE_UINTT,    userdata->lazy,       config, HK(lazy));
	
	userdata->values     = (userdata->key_values == 0) ? STRUCT_VALUES_WHOLE : STRUCT_VALUES_ONE;
	
	if(userdata->buffer == 0 && userdata->lazy == 0)
		return error("machine struct parameter buffer invalid");
	if(userdata->structure == NULL)
		return error("machine struct parameter structure invalid");
	
	return 0;
} // }}}
예제 #13
0
static ssize_t allocator_new(allocator_fixed_t **pfdata, hash_t *config){ // {{{
	ssize_t                ret;
	data_t                *sample;
	allocator_fixed_t     *fdata;
	
	if((fdata = calloc(1, sizeof(allocator_fixed_t))) == NULL)
		return error("calloc failed");
	
	pthread_rwlock_init(&fdata->rwlock, NULL);
	
	// get removed items tracker
	hash_holder_consume(ret, fdata->removed_items, config, HK(removed_items));
	hash_holder_consume(ret, fdata->storage,       config, HK(storage));
	if(ret != 0){
		ret = error("invalid storage supplied");
		goto error;
	}
	
	hash_data_get(ret, TYPE_UINTT, fdata->item_size, config, HK(item_size));
	if(ret != 0){
		if( (sample = hash_data_find(config, HK(item_sample))) == NULL){
			ret = error("no item_size nor item_sample supplied");
			goto error;
		}
		
		fastcall_length r_len = { { 4, ACTION_LENGTH }, 0, FORMAT(binary) };
		if( data_query(sample, &r_len) != 0 ){
			ret = error("bad item_sample");
			goto error;
		}
		
		fdata->item_size = r_len.length;
	}
	if(fdata->item_size == 0){
		ret = error("bad item size");
		goto error;
	}
	
	// get last id
	fastcall_length r_len = { { 4, ACTION_LENGTH }, 0, FORMAT(clean) };
	if( data_query(&fdata->storage, &r_len) != 0){
		ret = error("bad underlying storage");
		goto error;
	}
	fdata->last_id = r_len.length / fdata->item_size;
	
	*pfdata = fdata;
	return 0;

error:
	allocator_destroy(fdata);
	return ret;
} // }}}
예제 #14
0
파일: morph.c 프로젝트: samuell/frozen
static ssize_t morph_configure(machine_t *machine, config_t *config){ // {{{
	ssize_t                ret;
	morph_userdata      *userdata          = (morph_userdata *)machine->userdata;
	
	hash_data_get    (ret, TYPE_UINTT, userdata->pass_first,     config, HK(pass_first));
	hash_data_consume(ret, TYPE_HASHT, userdata->machine_config, config, HK(config));
	if(ret != 0)
		return error("HK(config) not supplied");
	
	//userdata->running = 0; // calloc in init already set it
	return 0;
} // }}}
예제 #15
0
ssize_t ipc_shmem_query   (ipc_t *ipc, request_t *request){ // {{{
	ssize_t                ret;
	uintmax_t              f_async           = 0;
	data_t                *buffer;
	ipc_shmem_block       *block;
	ipc_shmem_userdata    *userdata          = (ipc_shmem_userdata *)ipc->userdata;
	
	// check async state
	switch(userdata->forced_state){
		case FORCE_SYNC:  break; // already == 0
		case FORCE_ASYNC: f_async = 1; break;
		case FORCE_NONE:  hash_data_get(ret, TYPE_UINTT, f_async, request, HK(async)); break;
	};
	
	buffer = hash_data_find(request, userdata->buffer);
	
	// send request
	if( (block = shmem_get_block(userdata, STATUS_FREE, STATUS_WRITING)) == NULL)
		return error("strange error");
	
	// write data to ipc memory
	data_t               d_ipcmem  = DATA_RAW(userdata->shmdata + block->data_rel_ptr, userdata->shmaddr->item_size);
	fastcall_convert_to  r_convert = { { 4, ACTION_CONVERT_TO }, &d_ipcmem, FORMAT(packed) };
	if( (ret = data_query(buffer, &r_convert)) < 0)
		return error("can not write buffer to ipc memory");
	
	//block->size          = r_read.buffer_size;
	block->return_result = (f_async == 0) ? 1 : 0;
	
	if( (ret = shmem_block_status(userdata, block, STATUS_WRITING, STATUS_WRITTEN)) < 0)
		return ret;
	
	if(f_async == 0){ // synchronous request
		// wait for answer
		sem_wait(&block->sem_done);
		
		// read request back
		if(userdata->return_result != 0){
			fastcall_convert_from r_convert_from = { { 5, ACTION_CONVERT_FROM }, &d_ipcmem, FORMAT(packed) };
			data_query(buffer, &r_convert_from);
		}
		ret = 0;
		
		if(shmem_block_status(userdata, block, STATUS_EXEC_DONE, STATUS_FREE) < 0)
			return error("strange error 3");
	}else{
		ret = 0; // success
	}
	return ret;
} // }}}
예제 #16
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     action_pack_to_fast(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	action_t               action;
	data_t                *input;
	data_t                *output;
	format_t               format            = FORMAT(packed);
	
	hash_data_get(ret, TYPE_ACTIONT, action, request, HK(action));
	if(ret != 0)
		return ret;
	
	hash_data_get(ret, TYPE_FORMATT, format, request, HK(format));
	
	input  = hash_data_find(request, HK(input));
	output = hash_data_find(request, HK(output));
	
	if(!input || !output)
		return -EINVAL;
	
	data_realholder(ret, input, input);
	if(ret < 0)
		return ret;
	data_realholder(ret, output, output);
	if(ret < 0)
		return ret;
	
	fastcall_pack fargs = { { 6, action }, input, output, format };
	ret = callback(userdata, &fargs);
	
	data_t                *buffer            = hash_data_find(request, HK(size));
	fastcall_write         r_write           = { { 5, ACTION_WRITE }, 0, &fargs.transfered, sizeof(fargs.transfered) };
	if(buffer)
		data_query(buffer, &r_write);
	
	return ret;
} // }}}
예제 #17
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     api_convert_request_to_fastcall(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	action_t               action;
	f_convert_to_fast      func;
	
	hash_data_get(ret, TYPE_ACTIONT, action, request, HK(action));
	if(
		ret != 0 ||
		action >= ACTION_INVALID ||
		(func = api_convert_to_fast[action]) == NULL
	)
		return -ENOSYS;
	
	return func(userdata, request, callback);
} // }}}
예제 #18
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     action_length_to_fast(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	format_t               format            = FORMAT(native);
	
	hash_data_get(ret, TYPE_FORMATT, format, request, HK(format));
	
	fastcall_length        fargs             = { { 4, ACTION_LENGTH }, 0, format };
	ret = callback(userdata, &fargs);
	
	data_t                *buffer            = hash_data_find(request, HK(size));
	fastcall_write         r_write           = { { 5, ACTION_WRITE }, 0, &fargs.length, sizeof(fargs.length) };
	if(buffer)
		data_query(buffer, &r_write);
	
	return ret;
} // }}}
예제 #19
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     action_convert_from_to_fast(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	data_t                *input;
	format_t               format            = FORMAT(native);
	
	hash_data_get(ret, TYPE_FORMATT, format, request, HK(format));
	
	if( (input = hash_data_find(request, HK(source))) == NULL)
		return -EINVAL;
	
	fastcall_convert_from    fargs             = { { 5, ACTION_CONVERT_FROM }, input, format };
	ret = callback(userdata, &fargs);
	
	data_t                *buffer            = hash_data_find(request, HK(size));
	fastcall_write         r_write           = { { 5, ACTION_WRITE }, 0, &fargs.transfered, sizeof(fargs.transfered) };
	if(buffer)
		data_query(buffer, &r_write);
	
	return ret;
} // }}}
예제 #20
0
파일: structs.c 프로젝트: samuell/frozen
static ssize_t struct_machine_pack(machine_t *machine, request_t *request){
	ssize_t          ret;
	size_t           struct_size;
	data_t          *buffer;
	request_t       *values;
	struct_userdata *userdata = (struct_userdata *)machine->userdata;
		
	switch(userdata->values){
		case STRUCT_VALUES_WHOLE: values = request; break;
		case STRUCT_VALUES_ONE:
			hash_data_get(ret, TYPE_HASHT, values, request, userdata->key_values);
			if(ret != 0)
				return error("hash with keys not supplied");
			break;
	};
	
	if(userdata->lazy == 1){
		request_t r_next[] = {
			{ userdata->buffer, DATA_STRUCTT(userdata->structure, values) },
			hash_next(request)
		};
		
		return machine_pass(machine, r_next);
	}else{
		buffer = hash_data_find(request, userdata->buffer);
		if(buffer != NULL){
			if( (struct_size = struct_pack(userdata->structure, values, buffer)) == 0)
				return error("struct_pack failed");
			
			request_t new_request[] = {
				{ userdata->size, DATA_SIZET(struct_size) },
				hash_next(request)
			};
			
			return machine_pass(machine, new_request);
		}
		return machine_pass(machine, request);
	}
}
예제 #21
0
파일: structs.c 프로젝트: samuell/frozen
static ssize_t struct_machine_unpack(machine_t *machine, request_t *request){
	ssize_t          ret;
	data_t          *buffer;
	request_t       *values;
	struct_userdata *userdata = (struct_userdata *)machine->userdata;
	
	buffer = hash_data_find(request, userdata->buffer);
	if(buffer != NULL){
		switch(userdata->values){
			case STRUCT_VALUES_WHOLE: values = request; break;
			case STRUCT_VALUES_ONE:
				hash_data_get(ret, TYPE_HASHT, values, request, userdata->key_values);
				if(ret != 0)
					return error("hash with keys not supplied");
				break;
		};
		
		if(struct_unpack(userdata->structure, values, buffer) == 0)
			return error("struct_unpack failed");
	}
	
	return machine_pass(machine, request);
}
예제 #22
0
파일: api.c 프로젝트: samuell/frozen
ssize_t     action_query_to_fast(void *userdata, request_t *request, f_hash_to_fast callback){ // {{{
	ssize_t                ret;
	request_t             *t, *n;
	request_t             *q_request;
	request_t             *q_request_clean   = NULL;
	
	hash_data_get(ret, TYPE_HASHT, q_request, request, HK(request));
	if(ret != 0)
		return -EINVAL;
	
	if(hash_iter(q_request, (hash_iterator)&remove_symlinks, &q_request_clean, 0) == ITER_OK){
		fastcall_query         fargs             = { { 3, ACTION_QUERY }, q_request_clean };
		ret = callback(userdata, &fargs);
	}else{
		ret = -EFAULT;
	}
	
	for(t = q_request_clean; t; t = n){
		n = t[1].data.ptr; // inline hash
		
		free(t);
	}
	return ret;
} // }}}
예제 #23
0
파일: file_t.c 프로젝트: shalstvedt/frozen
static ssize_t file_new(file_t **pfdata, config_t *config){ // {{{
	ssize_t                ret;
	file_t                *fdata;
	char                   filepath[DEF_BUFFER_SIZE];
	uintmax_t              flags             = 0;
	data_t                *cfg_filename;
	uintmax_t              cfg_rdonly        = 0;
	uintmax_t              cfg_excl          = 0;
	uintmax_t              cfg_creat         = 1;
	uintmax_t              cfg_retry         = 0;
	uintmax_t              cfg_append        = 0;
	uintmax_t              cfg_trunc         = 0;
	uintmax_t              cfg_mode          = S_IRUSR | S_IWUSR;

	if( (fdata = calloc(1, sizeof(file_t))) == NULL)
		return error("calloc returns null");
	
	hash_data_get(ret, TYPE_UINTT, cfg_rdonly,   config, HK(readonly));
	hash_data_get(ret, TYPE_UINTT, cfg_excl,     config, HK(exclusive));
	hash_data_get(ret, TYPE_UINTT, cfg_creat,    config, HK(create));
	hash_data_get(ret, TYPE_UINTT, cfg_mode,     config, HK(mode));
	hash_data_get(ret, TYPE_UINTT, cfg_retry,    config, HK(retry));
	hash_data_get(ret, TYPE_UINTT, cfg_append,   config, HK(append));
	hash_data_get(ret, TYPE_UINTT, cfg_trunc,    config, HK(truncate));
	hash_data_get(ret, TYPE_UINTT, fdata->temprorary, config, HK(temprorary));
	
	if( (cfg_filename = hash_data_find(config, HK(filename))) == NULL){
		ret = error("filename not supplied");
		goto error;
	}

retry:;
	// get filepath
	fastcall_read r_read = { { 5, ACTION_READ }, 0, filepath, sizeof(filepath) - 1 };
	if(data_query(cfg_filename, &r_read) < 0){
		ret = error("filename invalid");
		goto error;
	}
	filepath[r_read.buffer_size] = '\0';
	
	// assign flags
	flags |= cfg_rdonly == 1 ? O_RDONLY : O_RDWR;
	flags |= cfg_excl   == 1 ? O_EXCL   : 0;
	flags |= cfg_creat  == 1 ? O_CREAT  : 0;
	flags |= cfg_append == 1 ? O_APPEND : 0;
	flags |= cfg_trunc  == 1 ? O_TRUNC  : 0;
	#ifdef O_LARGEFILE
	flags |= O_LARGEFILE;
	#endif
	
	if( (fdata->handle = open(filepath, flags, cfg_mode)) == -1){
		if(cfg_retry == 1)
			goto retry;
		
		ret = error("file open() error");
		goto error;
	}
	
	if(fdata->temprorary != 0){
		fdata->path = strdup(filepath);
	}
	
	*pfdata = fdata;
	return 0;
	
error:
	file_destroy(fdata);
	return ret;
} // }}}
예제 #24
0
ssize_t ipc_shmem_init    (ipc_t *ipc, config_t *config){ // {{{
	ssize_t                ret;
	int                    shmid;
	uint32_t               shmkey;
	size_t                 shmsize;
	size_t                 nitems            = NITEMS_DEFAULT;
	size_t                 item_size         = ITEM_SIZE_DEFAULT;
	uintmax_t              f_async           = 0;
	uintmax_t              f_sync            = 0;
	char                  *role_str          = NULL;
	ipc_shmem_userdata    *userdata          = (ipc_shmem_userdata *)ipc->userdata;
	
	userdata->buffer        = HK(buffer);
	userdata->return_result = 1;
	
	hash_data_get(ret, TYPE_UINT32T, shmkey,     config, HK(key));  if(ret != 0) return error("no key supplied");
	hash_data_convert(ret, TYPE_STRINGT, role_str,   config, HK(role)); if(ret != 0) return error("no role supplied");
	hash_data_get(ret, TYPE_SIZET,   item_size,  config, HK(item_size));
	hash_data_get(ret, TYPE_SIZET,   nitems,     config, HK(size));
	hash_data_get(ret, TYPE_UINTT,   f_async,    config, HK(force_async));
	hash_data_get(ret, TYPE_UINTT,   f_sync,     config, HK(force_sync));
	hash_data_get(ret, TYPE_HASHKEYT, userdata->buffer,   config, HK(buffer));
	hash_data_get(ret, TYPE_UINTT,    userdata->return_result, config, HK(return_result));
	
	if( (userdata->role = ipc_string_to_role(role_str)) == ROLE_INVALID)
		return error("invalid role supplied");
	
	free(role_str);
	
	shmsize = nitems * sizeof(ipc_shmem_block) + nitems * item_size + sizeof(ipc_shmem_header); 
	
	if( (shmid = shmget(shmkey, shmsize, IPC_CREAT | 0666)) < 0)
		return error("shmget failed");
	
	if( (userdata->shmaddr = shmat(shmid, NULL, 0)) == (void *)-1)
		return error("shmat failed");
	
	if( (f_async != 0 && f_sync != 0) )
		return error("force_async with force_sync");
	
	userdata->shmblocks = (ipc_shmem_block *)((void *)userdata->shmaddr   + sizeof(ipc_shmem_header));
	userdata->shmdata   = (void *)           ((void *)userdata->shmblocks + nitems * sizeof(ipc_shmem_block));
	userdata->inited    = 1;
	
	userdata->forced_state = FORCE_NONE;
	if(f_async != 0) userdata->forced_state = FORCE_ASYNC;
	if(f_sync  != 0) userdata->forced_state = FORCE_SYNC;
	
	if(userdata->role == ROLE_SERVER){
		userdata->shmaddr->item_size = item_size;
		userdata->shmaddr->nitems    = nitems;
		
		if(shmem_init(userdata) != 0)
			return error("shmem_init failed");
		
		// start threads
		if(pthread_create(&userdata->server_thr, NULL, &ipc_shmem_listen, ipc) != 0)
			return error("pthread_create failed");
	}
	return 0;
} // }}}