static ssize_t data_format_t_convert_to(data_t *src, fastcall_convert_to *fargs){ // {{{ ssize_t ret; format_t value; uintmax_t transfered; keypair_t *kp; void *iter = NULL; char *string = "(unknown)"; if(fargs->dest == NULL || src->ptr == NULL) return -EINVAL; value = *(format_t *)src->ptr; switch(fargs->format){ case FORMAT(config):; case FORMAT(clean):; case FORMAT(human):; // find in static keys first for(kp = &formats[0]; kp->key_str != NULL; kp++){ if(kp->key_val == value){ string = kp->key_str; goto found; } } #ifdef RESOLVE_DYNAMIC_KEYS // find in dynamic keys list_rdlock(&dynamic_formats); while( (kp = list_iter_next(&dynamic_formats, &iter)) != NULL){ if(kp->key_val == value){ string = kp->key_str; list_unlock(&dynamic_formats); goto found; } } list_unlock(&dynamic_formats); #endif found:; fastcall_write r_write = { { 5, ACTION_WRITE }, 0, string, strlen(string) }; ret = data_query(fargs->dest, &r_write); transfered = r_write.buffer_size; break; default: return -ENOSYS; } if(fargs->header.nargs >= 5) fargs->transfered = transfered; return ret; } // }}}
static ssize_t data_format_t_convert_from(data_t *dst, fastcall_convert_from *fargs){ // {{{ uintmax_t i = 1; char c; char buffer[DEF_BUFFER_SIZE] = { 0 }; char *p = buffer; keypair_t *kp; format_t key_val = 0; if(fargs->src == NULL) return -EINVAL; if(dst->ptr == NULL){ // no buffer, alloc new if( (dst->ptr = malloc(sizeof(format_t))) == NULL) return -ENOMEM; } switch(fargs->format){ case FORMAT(config):; case FORMAT(human):; fastcall_read r_read = { { 5, ACTION_READ }, 0, &buffer, sizeof(buffer) - 1 }; if(data_query(fargs->src, &r_read) != 0) return -EFAULT; while((c = *p++)){ key_val += c * i * i; i++; } #ifdef COLLISION_CHECK #ifdef STATIC_KEYS_CHECK // find collisions for(kp = &formats[0]; kp->key_str != NULL; kp++){ if(kp->key_val == key_val && strcmp(kp->key_str, buffer) != 0) goto collision; } #endif #ifdef DYNAMIC_KEYS_CHECK void *iter = NULL; list_rdlock(&dynamic_formats); while( (kp = list_iter_next(&dynamic_formats, &iter)) != NULL){ if(kp->key_val == key_val && strcmp(kp->key_str, buffer) != 0){ list_unlock(&dynamic_formats); goto collision; } } list_unlock(&dynamic_formats); #endif #endif #if defined DYNAMIC_KEYS_CHECK || defined RESOLVE_DYNAMIC_KEYS keypair_t *newkey = malloc(sizeof(keypair_t)); newkey->key_str = strdup(buffer); newkey->key_val = key_val; list_add(&dynamic_formats, newkey); #endif *(format_t *)(dst->ptr) = key_val; return 0; default: break; } return -ENOSYS; goto collision; // dummy collision: // report collision fprintf(stderr, "format collision: %s <=> %s\n", kp->key_str, buffer); return error("format collision"); } // }}}
void limit_group_limit(list *machines, rule *rule, uintmax_t need_lock){ // {{{ uintmax_t i, lsz; uintmax_t parameter; uintmax_t parameter_group; machine_t *machine; limit_userdata *machine_ud; machine_t **lchilds; if(rule->limit == __MAX(uintmax_t)) // no limits return; if(need_lock == 1) list_rdlock(machines); if( (lsz = list_count(machines)) != 0){ lchilds = alloca( sizeof(machine_t *) * lsz ); list_flatten(machines, (void **)lchilds, lsz); repeat:; parameter_group = 0; machine_t *machine_first = NULL; machine_t *machine_last = NULL; machine_t *machine_high = NULL; machine_t *machine_low = NULL; for(i=0; i<lsz; i++){ machine = lchilds[i]; machine_ud = (limit_userdata *)machine->userdata; if( (parameter = machine_ud->usage_parameter) == 0) continue; parameter_group += parameter; #define limit_kill_check(_machine, _field, _moreless) { \ if(_machine == NULL){ \ _machine = machine; \ }else{ \ if(machine_ud->_field _moreless ((limit_userdata *)_machine->userdata)->_field) \ _machine = machine; \ } \ } limit_kill_check(machine_first, created_on, <); limit_kill_check(machine_last, created_on, >); limit_kill_check(machine_low, usage_parameter, <); limit_kill_check(machine_high, usage_parameter, >); } if(parameter_group >= rule->limit){ switch(rule->mode){ case METHOD_RANDOM: machine = lchilds[ random() % lsz ]; break; case METHOD_FIRST: machine = machine_first; break; case METHOD_LAST: machine = machine_last; break; case METHOD_HIGHEST: machine = machine_high; break; case METHOD_LOWEST: machine = machine_low; break; default: machine = NULL; break; }; if(machine != NULL){ limit_machine_action(machine, rule); goto repeat; } } }