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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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); } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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; } // }}}
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); } // }}}
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; } // }}}
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; } // }}}
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); } }
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); }
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; } // }}}
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; } // }}}
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; } // }}}