/*! Steal a block with available vma[s]. */ static struct block * S_block_steal_and_lock(void) { int ret; struct block * block; struct superblock * superblock; /* Lock S_gpool. */ LOCK_GET(&(S_gpool.lock), S_gpool.lctr); if (NULL == (superblock=S_superblock_get_and_lock())) { /* Unlock S_gpool. */ LOCK_LET(&(S_gpool.lock)); return NULL; } /* superblock will be locked by superblock_get(). */ /* Get head of superblock's block list. */ block = superblock->head; /* Lock block. */ LOCK_GET(&(block->lock), block->lctr); /* Remove block from front of superblock's block list. */ superblock->head = block->next; if (NULL != block->next) { block->next->prev = block->prev; } /* Increment superblock's block count. */ superblock->bctr++; if (NULL == superblock->head) { /* Remove superblock from front of S_gpool's superblock list. */ S_gpool.head = superblock->next; if (NULL != superblock->next) { superblock->next->prev = superblock->prev; } assert(SUPERBLOCK_CTR_FULL == superblock->bctr); } /* Unlock superblock. */ LOCK_LET(&(superblock->lock)); /* Unlock S_gpool. */ LOCK_LET(&(S_gpool.lock)); DBG_LOG(stderr, "stole block %p-%p\n", (void*)block,\ (void*)((char*)block+BLOCK_SIZE)); return block; }
/*! Free a superblock with no used blocks. */ static void S_superblock_unlock_and_put(struct superblock * const superblock) { int ret; /* Lock S_gpool. */ LOCK_GET(&(S_gpool.lock), S_gpool.lctr); /* Remove superblock from S_gpool's superblock list. */ if (S_gpool.head == superblock) { S_gpool.head = superblock->next; } else { superblock->prev->next = superblock->next; } if (NULL != superblock->next) { superblock->next->prev = superblock->prev; } /* Unlock S_gpool. */ LOCK_LET(&(S_gpool.lock)); /* Unlock superblock. */ LOCK_LET(&(superblock->lock)); /* Free superblock's lock. */ ret = lock_free(&(superblock->lock)); assert(!ret); /* Destroy superblock's block list. */ S_superblock_list_destroy(superblock); /* Lock S_gpool. */ LOCK_GET(&(S_gpool.lock), S_gpool.lctr); /* Accumulate superblock's block wait counter. */ S_gpool.blctr += superblock->blctr; /* Accumulate superblock's wait counter. */ S_gpool.slctr += superblock->lctr; /* Unlock S_gpool. */ LOCK_LET(&(S_gpool.lock)); /* Release back to system. */ ret = CALL_SYS_FREE(superblock, SUPERBLOCK_SIZE); assert(SYS_FREE_FAIL != ret); DBG_LOG(stderr, "put superblock %p-%p\n", (void*)superblock,\ (void*)((char*)superblock+SUPERBLOCK_SIZE)); }
static int bdb_cache_entry_db_lock( struct bdb_info *bdb, DB_TXN *txn, EntryInfo *ei, int rw, int tryOnly, DB_LOCK *lock ) { #ifdef NO_DB_LOCK return 0; #else int rc; DBT lockobj; int db_rw; if ( !lock ) return 0; if (rw) db_rw = DB_LOCK_WRITE; else db_rw = DB_LOCK_READ; DBTzero( &lockobj ); lockobj.data = &ei->bei_id; lockobj.size = sizeof(ei->bei_id) + 1; rc = LOCK_GET(bdb->bi_dbenv, TXN_ID(txn), tryOnly ? DB_LOCK_NOWAIT : 0, &lockobj, db_rw, lock); if (rc && !tryOnly) { Debug( LDAP_DEBUG_TRACE, "bdb_cache_entry_db_lock: entry %ld, rw %d, rc %d\n", ei->bei_id, rw, rc ); } return rc; #endif /* NO_DB_LOCK */ }
int bdb_cache_entry_db_lock ( DB_ENV *env, u_int32_t locker, Entry *e, int rw, u_int32_t flags, DB_LOCK *lock ) { #ifdef NO_THREADS return 0; #else int rc; DBT lockobj; int db_rw; if (rw) db_rw = DB_LOCK_WRITE; else db_rw = DB_LOCK_READ; lockobj.data = e->e_nname.bv_val; lockobj.size = e->e_nname.bv_len; rc = LOCK_GET(env, locker, flags | DB_LOCK_NOWAIT, &lockobj, db_rw, lock); if (rc) { #ifdef NEW_LOGGING LDAP_LOG( CACHE, DETAIL1, "bdb_cache_entry_db_lock: entry %s, rw %d, rc %d\n", e->e_nname.bv_val, rw, rc ); #else Debug( LDAP_DEBUG_TRACE, "bdb_cache_entry_db_lock: entry %s, rw %d, rc %d\n", e->e_nname.bv_val, rw, rc ); #endif } return rc; #endif /* NO_THREADS */ }
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); }
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_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); }
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_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; }
/*! This will test the functionality of S_superblock_unlock_and_put() when * superblock is the last superblock in S_gpool's superblock list. */ void superblock_4(void) { int ret; void * retp; struct superblock * superblock1, * superblock2; /* ---- SETUP ---- */ retp = CALL_SYS_ALLOC(superblock1, SUPERBLOCK_SIZE); assert(SYS_ALLOC_FAIL != retp); retp = CALL_SYS_ALLOC(superblock2, SUPERBLOCK_SIZE); assert(SYS_ALLOC_FAIL != retp); ret = lock_init(&(superblock1->lock)); assert(!ret); ret = lock_init(&(superblock2->lock)); assert(!ret); superblock1->prev = superblock2; superblock1->next = NULL; superblock2->prev = NULL; superblock2->next = superblock1; S_gpool.head = superblock2; LOCK_GET(&(superblock1->lock), null_ctr); /* ---- UNIT ---- */ S_superblock_unlock_and_put(superblock1); /* ---- ASSERTIONS ---- */ assert(superblock2 == S_gpool.head); assert(NULL == superblock2->prev); assert(NULL == superblock2->next); /* ---- CLEANUP ---- */ ret = CALL_SYS_FREE(superblock2, SUPERBLOCK_SIZE); assert(SYS_FREE_FAIL != ret); S_gpool.head = NULL; }
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); }
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; }
void vma_gpool_gather(void) { int ret; /* Lock S_gpool. */ LOCK_GET(&(S_gpool.lock), S_gpool.lctr); /* Accumulate threads's S_mpool wait counter. */ S_gpool.mlctr += S_mpool.lctr; /* Unlock S_gpool. */ LOCK_LET(&(S_gpool.lock)); }
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); }
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); }
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; }
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(); }
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_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 */ }
/*! Get a superblock with available block[s]. */ static struct superblock * S_superblock_get_and_lock(void) { int ret; void * retp; struct superblock * superblock; if (NULL == (superblock=S_gpool.head)) { /* Allocate new superblock. */ retp = CALL_SYS_ALLOC(superblock, SUPERBLOCK_SIZE); if (SYS_ALLOC_FAIL == retp) { return NULL; } S_gpool.actr++; /* Prepend superblock to S_gpool's superblock list. */ S_gpool.head = superblock; superblock->prev = NULL; superblock->next = NULL; /* Setup superblock. */ superblock->bctr = 0; superblock->lctr = 0; superblock->blctr = 0; /* Initialize superblock's lock. */ ret = lock_init(&(superblock->lock)); assert(!ret); /* Setup superblock's block list. */ S_superblock_list_setup(superblock); } /* Lock superblock. */ LOCK_GET(&(superblock->lock), superblock->lctr); DBG_LOG(stderr, "got superblock %p-%p\n", (void*)superblock,\ (void*)((char*)superblock+SUPERBLOCK_SIZE)); return superblock; }
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 int bdb_dn2id_lock( struct bdb_info *bdb, struct berval *dn, int rw, DB_TXN *txn, DB_LOCK *lock ) { int rc; DBT lockobj; int db_rw; if (!txn) return 0; if (rw) db_rw = DB_LOCK_WRITE; else db_rw = DB_LOCK_READ; lockobj.data = dn->bv_val; lockobj.size = dn->bv_len; rc = LOCK_GET(bdb->bi_dbenv, TXN_ID(txn), DB_LOCK_NOWAIT, &lockobj, db_rw, lock); return rc; }
/* 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; }