static void rpc_set_queue(rpc_t *rpc, void *c) { unsigned int queue_no = MAX_QUEUES, pipe_no = MAX_PIPES; str method, method_buf; if (rpc->scan(c, "dSd", &queue_no, &method, &pipe_no) < 3) return; if (pipe_no >= MAX_PIPES || (int)pipe_no < 0) { LM_ERR("Invalid pipe number: %d\n", pipe_no); rpc->fault(c, 400, "Invalid pipe number"); return; } if (str_cpy(&method_buf, &method)) { LM_ERR("out of memory\n"); rpc->fault(c, 400, "OOM"); return; } LOCK_GET(rl_lock); if (queue_no >= *nqueues) { LM_ERR("MAX_QUEUES reached for queue: %d\n", queue_no); rpc->fault(c, 400, "MAX_QUEUES reached"); LOCK_RELEASE(rl_lock); return; } *queues[queue_no].pipe = pipe_no; if (!queues[queue_no].method->s) shm_free(queues[queue_no].method->s); queues[queue_no].method->s = method_buf.s; queues[queue_no].method->len = method_buf.len; LOCK_RELEASE(rl_lock); }
struct mi_root* mi_get_pid(struct mi_root* cmd_tree, void* param) { struct mi_root *rpl_tree; struct mi_node *node=NULL, *rpl=NULL; struct mi_attr* attr; rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==0) return 0; rpl = &rpl_tree->node; node = add_mi_node_child(rpl, 0, "PID", 3, 0, 0); if(node == NULL) goto error; LOCK_GET(rl_lock); attr= addf_mi_attr(node, 0, "ki", 2, "%0.3f", *pid_ki); if(attr == NULL) goto error; attr= addf_mi_attr(node, 0, "kp", 2, "%0.3f", *pid_kp); if(attr == NULL) goto error; attr= addf_mi_attr(node, 0, "kd", 2, "%0.3f", *pid_kd); LOCK_RELEASE(rl_lock); if(attr == NULL) goto error; return rpl_tree; error: LOCK_RELEASE(rl_lock); LM_ERR("Unable to create reply\n"); free_mi_tree(rpl_tree); return 0; }
struct mi_root* mi_get_pipes(struct mi_root* cmd_tree, void* param) { struct mi_root *rpl_tree; struct mi_node *node=NULL, *rpl=NULL; struct mi_attr* attr; str algo; char* p; int i, len; rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==0) return 0; rpl = &rpl_tree->node; LOCK_GET(rl_lock); for (i=0; i<MAX_PIPES; i++) { if (*pipes[i].algo != PIPE_ALGO_NOP) { node = add_mi_node_child(rpl, 0, "PIPE", 4, 0, 0); if(node == NULL) goto error; p = int2str((unsigned long)(i), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "id" , 2, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(*pipes[i].algo), &len); if (str_map_int(algo_names, *pipes[i].algo, &algo)) goto error; attr = add_mi_attr(node, 0, "algorithm", 9, algo.s, algo.len); if(attr == NULL) goto error; p = int2str((unsigned long)(*pipes[i].limit), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "limit", 5, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(*pipes[i].counter), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "counter", 7, p, len); if(attr == NULL) goto error; } } LOCK_RELEASE(rl_lock); return rpl_tree; error: LOCK_RELEASE(rl_lock); LM_ERR("Unable to create reply\n"); free_mi_tree(rpl_tree); return 0; }
struct mi_root* mi_set_pipe(struct mi_root* cmd_tree, void* param) { struct mi_node *node; unsigned int pipe_no = MAX_PIPES, algo_id, limit = 0; //str algo; node = cmd_tree->node.kids; if (node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if ( !node->value.s || !node->value.len || strno2int(&node->value,&pipe_no)<0) goto bad_syntax; node = node->next; if ( !node->value.s || !node->value.len) goto bad_syntax; if (str_map_str(algo_names, &(node->value), (int*)&algo_id)) { LM_ERR("unknown algorithm: '%.*s'\n", node->value.len, node->value.s); goto bad_syntax; } node = node->next; if ( !node->value.s || !node->value.len || strno2int(&node->value,&limit)<0) goto bad_syntax; LM_DBG("set pipe: %d:%d:%d\n", pipe_no, algo_id, limit); if (pipe_no >= MAX_PIPES) { LM_ERR("wrong pipe_no: %d\n", pipe_no); goto bad_syntax; } LOCK_GET(rl_lock); *pipes[pipe_no].algo = algo_id; *pipes[pipe_no].limit = limit; if (check_feedback_setpoints(0)) { LM_ERR("feedback limits don't match\n"); goto error; } else { *pid_setpoint = 0.01 * (double)cfg_setpoint; } set_check_network_load(); LOCK_RELEASE(rl_lock); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); error: LOCK_RELEASE(rl_lock); bad_syntax: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }
struct mi_root* mi_set_queue(struct mi_root* cmd_tree, void* param) { struct mi_node *node; unsigned int queue_no = MAX_QUEUES, pipe_no = MAX_PIPES; str method; node = cmd_tree->node.kids; if (node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if ( !node->value.s || !node->value.len || strno2int(&node->value,&queue_no)<0) goto bad_syntax; node = node->next; if ( !node->value.s || !node->value.len ) goto bad_syntax; if (str_cpy(&method, &(node->value))) { LM_ERR("out of memory\n"); goto early_error; } node = node->next; if ( !node->value.s || !node->value.len || strno2int(&node->value,&pipe_no)<0) goto early_error; if (pipe_no >= MAX_PIPES) { LM_ERR("invalid pipe number: %d\n", pipe_no); goto early_error; } LOCK_GET(rl_lock); if (queue_no >= *nqueues) { LM_ERR("MAX_QUEUES reached for queue: %d\n", queue_no); goto error; } *queues[queue_no].pipe = pipe_no; if (!queues[queue_no].method->s) shm_free(queues[queue_no].method->s); queues[queue_no].method->s = method.s; queues[queue_no].method->len = method.len; LOCK_RELEASE(rl_lock); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); error: LOCK_RELEASE(rl_lock); early_error: shm_free(method.s); bad_syntax: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }
/* mi function implementations */ struct mi_root* mi_stats(struct mi_root* cmd_tree, void* param) { struct mi_root *rpl_tree; struct mi_node *node=NULL, *rpl=NULL; struct mi_attr* attr; char* p; int i, len; rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==0) return 0; rpl = &rpl_tree->node; LOCK_GET(rl_lock); for (i=0; i<MAX_PIPES; i++) { if (*pipes[i].algo != PIPE_ALGO_NOP) { node = add_mi_node_child(rpl, 0, "PIPE", 4, 0, 0); if(node == NULL) goto error; p = int2str((unsigned long)(i), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "id", 2, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(*pipes[i].load), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "load", 4, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(*pipes[i].last_counter), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "counter", 7, p, len); if(attr == NULL) goto error; } } p = int2str((unsigned long)(*drop_rate), &len); node = add_mi_node_child(rpl, MI_DUP_VALUE, "DROP_RATE", 9, p, len); LOCK_RELEASE(rl_lock); return rpl_tree; error: LOCK_RELEASE(rl_lock); LM_ERR("Unable to create reply\n"); free_mi_tree(rpl_tree); return 0; }
struct mi_root* mi_set_pid(struct mi_root* cmd_tree, void* param) { struct mi_node *node; char i[5], p[5], d[5]; node = cmd_tree->node.kids; if (node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if ( !node->value.s || !node->value.len || node->value.len >= 5) goto bad_syntax; memcpy(i, node->value.s, node->value.len); i[node->value.len] = '\0'; node = node->next; if ( !node->value.s || !node->value.len || node->value.len >= 5) goto bad_syntax; memcpy(p, node->value.s, node->value.len); p[node->value.len] = '\0'; node = node->next; if ( !node->value.s || !node->value.len || node->value.len >= 5) goto bad_syntax; memcpy(d, node->value.s, node->value.len); d[node->value.len] = '\0'; LOCK_GET(rl_lock); *pid_ki = strtod(i, NULL); *pid_kp = strtod(p, NULL); *pid_kd = strtod(d, NULL); LOCK_RELEASE(rl_lock); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); bad_syntax: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }
struct mi_root* mi_push_load(struct mi_root* cmd_tree, void* param) { struct mi_node *node; double value; char c[5]; node = cmd_tree->node.kids; if (node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if ( !node->value.s || !node->value.len || node->value.len >= 5) goto bad_syntax; memcpy(c, node->value.s, node->value.len); c[node->value.len] = '\0'; value = strtod(c, NULL); if (value < 0.0 || value > 1.0) { LM_ERR("value out of range: %0.3f in not in [0.0,1.0]\n", value); goto bad_syntax; } LOCK_GET(rl_lock); *load_value = value; LOCK_RELEASE(rl_lock); do_update_load(); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); bad_syntax: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }
struct mi_root* mi_set_dbg(struct mi_root* cmd_tree, void* param) { struct mi_node *node; unsigned int dbg_mode = 0; node = cmd_tree->node.kids; if (node == NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if ( !node->value.s || !node->value.len || strno2int(&node->value,&dbg_mode)<0) goto bad_syntax; LOCK_GET(rl_lock); if (dbg_mode) { if (!rl_dbg_str->s) { rl_dbg_str->len = (MAX_PIPES * 5 * sizeof(char)); rl_dbg_str->s = (char *)shm_malloc(rl_dbg_str->len); if (!rl_dbg_str->s) { rl_dbg_str->len = 0; LM_ERR("oom: %d\n", rl_dbg_str->len); } } } else { if (rl_dbg_str->s) { shm_free(rl_dbg_str->s); rl_dbg_str->s = NULL; rl_dbg_str->len = 0; } } LOCK_RELEASE(rl_lock); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); bad_syntax: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }
static void rpc_set_pipe(rpc_t *rpc, void *c) { int pipe_no = MAX_PIPES, algo_id, limit = 0; str algo_str; if (rpc->scan(c, "dSd", &pipe_no, &algo_str, &limit) < 3) return; if (str_map_str(algo_names, &algo_str, &algo_id)) { LM_ERR("unknown algorithm: '%.*s'\n", algo_str.len, algo_str.s); rpc->fault(c, 400, "Unknown algorithm"); return; } LM_DBG("set_pipe: %d:%d:%d\n", pipe_no, algo_id, limit); if (pipe_no >= MAX_PIPES || pipe_no < 0) { LM_ERR("wrong pipe_no: %d\n", pipe_no); rpc->fault(c, 400, "Unknown pipe"); return; } LOCK_GET(rl_lock); *pipes[pipe_no].algo = algo_id; *pipes[pipe_no].limit = limit; if (check_feedback_setpoints(0)) { LM_ERR("feedback limits don't match\n"); rpc->fault(c, 400, "Feedback limits don't match"); } else { *pid_setpoint = 0.01 * (double)cfg_setpoint; } LOCK_RELEASE(rl_lock); }
struct mi_root* mi_get_queues(struct mi_root* cmd_tree, void* param) { struct mi_root *rpl_tree; struct mi_node *node=NULL, *rpl=NULL; struct mi_attr* attr; char* p; int i, len; rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==0) return 0; rpl = &rpl_tree->node; LOCK_GET(rl_lock); for (i=0; i<MAX_QUEUES; i++) { if (queues[i].pipe) { node = add_mi_node_child(rpl, 0, "QUEUE", 5, 0, 0); if(node == NULL) goto error; p = int2str((unsigned long)(i), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "id" , 2, p, len); if(attr == NULL) goto error; p = int2str((unsigned long)(*queues[i].pipe), &len); attr = add_mi_attr(node, MI_DUP_VALUE, "pipe" , 4, p, len); if(attr == NULL) goto error; attr = add_mi_attr(node, 0, "method", 6, (*queues[i].method).s, (*queues[i].method).len); if(attr == NULL) goto error; } } LOCK_RELEASE(rl_lock); return rpl_tree; error: LOCK_RELEASE(rl_lock); LM_ERR("Unable to create reply\n"); free_mi_tree(rpl_tree); return 0; }
static void rpc_set_pid(rpc_t *rpc, void *c) { double ki, kp, kd; if (rpc->scan(c, "fff", &ki, &kp, &kd) < 3) return; LOCK_GET(rl_lock); *pid_ki = ki; *pid_kp = kp; *pid_kd = kd; LOCK_RELEASE(rl_lock); }
/* rpc function implementations */ static void rpc_stats(rpc_t *rpc, void *c) { int i; LOCK_GET(rl_lock); for (i=0; i<MAX_PIPES; i++) { if (rpc->printf(c, "PIPE[%d]: %d/%d (drop rate: %d)", i, *pipes[i].last_counter, *pipes[i].limit, *pipes[i].load) < 0) goto error; } error: LOCK_RELEASE(rl_lock); }
static inline __always_inline void buf_release_all_locks(stm_tx_t *tx, stm_word_t version) { /* release all write locks */ lockset_t *mylocks = tx->lockset; stm_word_t i; if (version==0) { for (i=0; i<tx->nrlocks; i++) { stm_word_t *lockaddr = mylocks[i].lock; /* release the lock and save the version */ assert(*lockaddr==(stm_word_t)tx); LOCK_RELEASE(lockaddr, mylocks[i].version); } } else { for (i=0; i<tx->nrlocks; i++) { stm_word_t *lockaddr = mylocks[i].lock; /* release the lock and save the version */ assert(*lockaddr==(stm_word_t)tx); LOCK_RELEASE(lockaddr, version); } } }
/* mi function implementations */ struct mi_root* mi_stats(struct mi_root* cmd_tree, void* param) { struct mi_root *rpl_tree; struct mi_node *node=NULL, *rpl=NULL; struct mi_attr *attr; int len; char * p; node = cmd_tree->node.kids; rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN); if (rpl_tree==0) return 0; rpl = &rpl_tree->node; rpl->flags |= MI_IS_ARRAY; if (rl_stats(rpl_tree, &node->value)) { LM_ERR("cannot mi print values\n"); goto free; } if (!(node = add_mi_node_child(rpl, 0, "PIPE", 4, NULL, 0))) goto free; LOCK_GET(rl_lock); p = int2str((unsigned long)(*drop_rate), &len); if (!(attr = add_mi_attr(node, MI_DUP_VALUE, "drop_rate", 9, p, len))) { LOCK_RELEASE(rl_lock); goto free; } LOCK_RELEASE(rl_lock); return rpl_tree; free: free_mi_tree(rpl_tree); return 0; }
static void rpc_get_queues(rpc_t *rpc, void *c) { int i; LOCK_GET(rl_lock); for (i=0; i<MAX_QUEUES; i++) { if (queues[i].pipe) { if (rpc->printf(c, "QUEUE[%d]: %d:%.*s", i, *queues[i].pipe, (*queues[i].method).len, (*queues[i].method).s) < 0) goto error; } } error: LOCK_RELEASE(rl_lock); }
static void rpc_push_load(rpc_t *rpc, void *c) { double value; if (rpc->scan(c, "f", &value) < 1) return; if (value < 0.0 || value > 1.0) { LM_ERR("value out of range: %0.3f in not in [0.0,1.0]\n", value); rpc->fault(c, 400, "Value out of range"); return; } LOCK_GET(rl_lock); *load_value = value; LOCK_RELEASE(rl_lock); do_update_load(); }
static void rpc_get_pipes(rpc_t *rpc, void *c) { str algo; int i; LOCK_GET(rl_lock); for (i=0; i<MAX_PIPES; i++) { if (*pipes[i].algo != PIPE_ALGO_NOP) { if (str_map_int(algo_names, *pipes[i].algo, &algo)) goto error; if (rpc->printf(c, "PIPE[%d]: %d:%.*s %d/%d (drop rate: %d) [%d]", i, *pipes[i].algo, algo.len, algo.s, *pipes[i].last_counter, *pipes[i].limit, *pipes[i].load, *pipes[i].counter) < 0) goto error; } } error: LOCK_RELEASE(rl_lock); }
/* timer housekeeping, invoked each timer interval to reset counters */ static void rl_timer(unsigned int ticks, void *param) { int i, len; char *c, *p; LOCK_GET(rl_lock); switch (*load_source) { case LOAD_SOURCE_CPU: update_cpu_load(); break; } if (*check_network_load) { *network_load_value = get_total_bytes_waiting(PROTO_NONE); } if (rl_dbg_str->s) { c = p = rl_dbg_str->s; memset(c, ' ', rl_dbg_str->len); for (i=0; i<MAX_PIPES; i++) { c = int2str(*pipes[i].counter, &len); if (len < 4) { memcpy( p + (5-len), c, len ); } else { memset(p, '*', 5); LM_WARN("Counter pipes[%d] to big: %d\n", i, *pipes[i].counter); } p = p + 5; } LM_WARN("%.*s\n", rl_dbg_str->len, rl_dbg_str->s); } for (i=0; i<MAX_PIPES; i++) { if( *pipes[i].algo == PIPE_ALGO_NETWORK ) { *pipes[i].load = ( *network_load_value > *pipes[i].limit ) ? 1 : -1; } else if (*pipes[i].limit && timer_interval) { *pipes[i].load = *pipes[i].counter / (*pipes[i].limit * timer_interval); } *pipes[i].last_counter = *pipes[i].counter; *pipes[i].counter = 0; } LOCK_RELEASE(rl_lock); }
/* timer housekeeping, invoked each timer interval to reset counters */ static ticks_t rl_timer_handle(ticks_t ticks, struct timer_ln* tl, void* data) { int i, len; char *c, *p; LOCK_GET(rl_lock); switch (*load_source) { case LOAD_SOURCE_CPU: update_cpu_load(); break; } *network_load_value = get_total_bytes_waiting(); if (rl_dbg_str->s) { c = p = rl_dbg_str->s; memset(c, ' ', rl_dbg_str->len); for (i=0; i<MAX_PIPES; i++) { c = int2str(*pipes[i].counter, &len); if (len < 4) { memcpy( p + (5-len), c, len ); } else { memset(p, '*', 5); LM_WARN("Counter pipes[%d] to big: %d\n", i, *pipes[i].counter); } p = p + 5; } LM_WARN("%.*s\n", rl_dbg_str->len, rl_dbg_str->s); } for (i=0; i<MAX_PIPES; i++) { if( *pipes[i].algo == PIPE_ALGO_NETWORK ) { *pipes[i].load = ( *network_load_value > *pipes[i].limit ) ? 1 : -1; } else if (*pipes[i].limit && timer_interval) { *pipes[i].load = *pipes[i].counter / (*pipes[i].limit * timer_interval); } *pipes[i].last_counter = *pipes[i].counter; *pipes[i].counter = 0; } LOCK_RELEASE(rl_lock); return (ticks_t)(-1); /* periodical */ }
struct mi_root* mi_set_pid(struct mi_root* cmd_tree, void* param) { struct mi_node *node; char buf[5]; int rl_ki, rl_kp, rl_kd; if (!(node = cmd_tree->node.kids)) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if ( !node->value.s || !node->value.len || node->value.len >= 5) goto bad_syntax; memcpy(buf, node->value.s, node->value.len); buf[node->value.len] = '\0'; rl_ki = strtod(buf, NULL); node = node->next; if ( !node->value.s || !node->value.len || node->value.len >= 5) goto bad_syntax; memcpy(buf, node->value.s, node->value.len); buf[node->value.len] = '\0'; rl_kp = strtod(buf, NULL); node = node->next; if ( !node->value.s || !node->value.len || node->value.len >= 5) goto bad_syntax; memcpy(buf, node->value.s, node->value.len); buf[node->value.len] = '\0'; rl_kd = strtod(buf, NULL); LOCK_GET(rl_lock); *pid_ki = rl_ki; *pid_kp = rl_kp; *pid_kd = rl_kd; LOCK_RELEASE(rl_lock); return init_mi_tree( 200, MI_OK_S, MI_OK_LEN); bad_syntax: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }
/** * runs the current request through the queues * \param forced_pipe is >= 0 if a specific pipe should be used, < 0 otherwise * \return -1 if drop needed, 1 if allowed */ static int rl_check(struct sip_msg * msg, int forced_pipe) { int que_id, pipe_id, ret; str method = msg->first_line.u.request.method; LOCK_GET(rl_lock); if (forced_pipe < 0) { if (find_queue(msg, &que_id)) { pipe_id = que_id = 0; ret = 1; goto out_release; } pipe_id = *queues[que_id].pipe; } else { que_id = 0; pipe_id = forced_pipe; } ret = pipe_push(msg, pipe_id); out_release: LOCK_RELEASE(rl_lock); /* no locks here because it's only read and pipes[pipe_id] is always alloc'ed */ LOG(L_DBG, "meth=%.*s queue=%d pipe=%d algo=%d limit=%d pkg_load=%d counter=%d " "load=%2.1lf => %s\n", method.len, method.s, que_id, pipe_id, *pipes[pipe_id].algo, *pipes[pipe_id].limit, *pipes[pipe_id].load, *pipes[pipe_id].counter, *load_value, (ret == 1) ? "ACCEPT" : "DROP"); return ret; }
/** * runs the current request through the queues * \param forced_pipe is >= 0 if a specific pipe should be used, < 0 otherwise * \return -1 if drop needed, 1 if allowed */ static int rl_check(struct sip_msg * msg, int forced_pipe) { int que_id, pipe_id, ret; str method = msg->first_line.u.request.method; if (forced_pipe >=0 && (forced_pipe>=MAX_PIPES || *pipes[forced_pipe].algo==PIPE_ALGO_NOP)) { LM_ERR("forced pipe %d out of range or not defined " " => defaulting to method type checking\n", forced_pipe); forced_pipe = -1; } LOCK_GET(rl_lock); if (forced_pipe < 0) { if (find_queue(msg, &que_id)) { pipe_id = que_id = 0; ret = 1; goto out_release; } pipe_id = *queues[que_id].pipe; } else { que_id = 0; pipe_id = forced_pipe; } ret = pipe_push(msg, pipe_id); out_release: LOCK_RELEASE(rl_lock); /* no locks here because it's only read and pipes[pipe_id] is always alloc'ed */ LM_DBG("meth=%.*s queue=%d pipe=%d algo=%d limit=%d pkg_load=%d counter=%d " "load=%2.1lf network_load=%d => %s\n", method.len, method.s, que_id, pipe_id, *pipes[pipe_id].algo, *pipes[pipe_id].limit, *pipes[pipe_id].load, *pipes[pipe_id].counter, *load_value, *network_load_value, (ret == 1) ? "ACCEPT" : "DROP"); return ret; }
static void rpc_set_dbg(rpc_t *rpc, void *c) { int dbg_mode = 0; if (rpc->scan(c, "d", &dbg_mode) < 1) return; LOCK_GET(rl_lock); if (dbg_mode) { if (!rl_dbg_str->s) { rl_dbg_str->len = (MAX_PIPES * 5 * sizeof(char)); rl_dbg_str->s = (char *)shm_malloc(rl_dbg_str->len); if (!rl_dbg_str->s) { rl_dbg_str->len = 0; LM_ERR("oom: %d\n", rl_dbg_str->len); } } } else { if (rl_dbg_str->s) { shm_free(rl_dbg_str->s); rl_dbg_str->s = NULL; rl_dbg_str->len = 0; } } LOCK_RELEASE(rl_lock); }
void Text::setText(const char* text) { int length = strlen(text); if(length > 255) length = 255; memset(pTextBuffer, 0x00, 256); memcpy(pTextBuffer, text, length); const char* p; int width=0,height=0; /* calculate font scaling */ LOCK_ACQUIRE(gFtLock); //float scale = stbtt_ScaleForPixelHeight(gFontInfo, pPixelSize); float scale = stbtt_ScaleForMappingEmToPixels(gFontInfo, pPixelSize); int ascent, descent, lineGap; stbtt_GetFontVMetrics(gFontInfo, &ascent, &descent, &lineGap); ascent *= scale; descent *= scale; height = ascent; // calculate bitmap size for (p = pTextBuffer; *p; p++) { /* how wide is this character */ int ax; stbtt_GetCodepointHMetrics(gFontInfo, p[0], &ax, 0); width += ax * scale; /* add kerning */ int kern; kern = stbtt_GetCodepointKernAdvance(gFontInfo, p[0], p[1]); width += kern * scale; } //check if old bitmap exists, and delete it uint8_t* oldBitmap = pBitmap; pBitmap = (uint8_t*)malloc(width*height); if(oldBitmap) { free(oldBitmap); } memset(pBitmap,0,width*height); pBitmapWidth = width; pBitmapHeight = height; setSizeN( 2.f*((float)pBitmapWidth)/GetCore()->screen_width, 2.f*((float)pBitmapHeight)/GetCore()->screen_width ); int x=0,y=0; // render text to buffer for (p = pTextBuffer; *p; p++) { /* get bounding box for character (may be offset to account for chars that dip above or below the line */ int c_x1, c_y1, c_x2, c_y2; stbtt_GetCodepointBitmapBox(gFontInfo, p[0], scale, scale, &c_x1, &c_y1, &c_x2, &c_y2); /* compute y (different characters have different heights */ y = ascent + c_y1; /* render character (stride and offset is important here) */ int byteOffset = x + (y * width); stbtt_MakeCodepointBitmap(gFontInfo, pBitmap + byteOffset, c_x2 - c_x1, c_y2 - c_y1, width, scale, scale, p[0]); /* how wide is this character */ int ax; stbtt_GetCodepointHMetrics(gFontInfo, p[0], &ax, 0); x += ax * scale; /* add kerning */ int kern; kern = stbtt_GetCodepointKernAdvance(gFontInfo, p[0], p[1]); x += kern * scale; } LOCK_RELEASE(gFtLock); updateBitmap = true; }