/** * set the flag of the connection identified by 'jkey' * */ int xj_wlist_set_flag(xj_wlist jwl, xj_jkey jkey, int fl) { int i; xj_jkey p = NULL; if(jwl==NULL || jkey==NULL || jkey->id==NULL || jkey->id->s==NULL) return -1; #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_wlist_set_flag: looking for <%.*s>" " having id=%d\n", jkey->id->len, jkey->id->s, jkey->hash); #endif i = 0; while(i < jwl->len) { lock_set_get(jwl->sems, i); if(jwl->workers[i].pid <= 0) { lock_set_release(jwl->sems, i); i++; continue; } if((p=find234(jwl->workers[i].sip_ids, (void*)jkey, NULL)) != NULL) { p->flag = fl; lock_set_release(jwl->sems, i); #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_wlist_set_flag: the connection for <%.*s>" " marked with flag=%d", jkey->id->len, jkey->id->s, fl); #endif return jwl->workers[i].wpipe; } lock_set_release(jwl->sems, i); i++; } #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_wlist_set_flag: entry does not exist for <%.*s>\n", jkey->id->len, jkey->id->s); #endif return -1; }
int get_dynamic_lock(struct sip_msg *msg, char *string) { str ret; int hash; if (((gparam_p)string)->type == GPARAM_TYPE_STR) { LM_INFO("Static string given! get_static_lock() function is better!\n"); } if (fixup_get_svalue(msg, (gparam_p)string, &ret) != 0) { LM_ERR("Get string from fixup param failed!\n"); return -1; } hash = (int)core_hash(&ret, NULL, lock_pool_size); LM_DBG("Getting dynamic lock----- %d\n", hash); lock_set_get(dynamic_locks, hash); LM_DBG("Got dynamic lock----- %d\n", hash); return 1; }
/** * send disconnected info to all SIP users associated with worker idx * and clean the entries from wlist */ int xj_wlist_clean_jobs(xj_wlist jwl, int idx, int fl) { xj_jkey p; if(jwl==NULL || idx < 0 || idx >= jwl->len || !jwl->workers[idx].sip_ids) return -1; lock_set_get(jwl->sems, idx); while((p=(xj_jkey)delpos234(jwl->workers[idx].sip_ids, 0))!=NULL) { if(fl) { #ifdef XJ_EXTRA_DEBUG DBG("XJAB:xj_wlist_send_info: sending disconnect message" " to <%.*s>\n", p->id->len, p->id->s); #endif xj_send_sip_msgz(_PADDR(jwl), p->id, &jab_gw_name, XJ_DMSG_INF_DISCONNECTED, NULL); } jwl->workers[idx].nr--; xj_jkey_free_p(p); } lock_set_release(jwl->sems, idx); return 0; }
/** * return communication pipe with the worker that will process the message for * the id 'sid' only if it exists, or -1 if error * - jwl : pointer to the workers list * - sid : id of the entity (connection to Jabber - usually SHOULD be FROM * header of the incoming SIP message) * - p : will point to the SHM location of the 'sid' in jwl */ int xj_wlist_check(xj_wlist jwl, xj_jkey jkey, xj_jkey *p) { int i; if(jwl==NULL || jkey==NULL || jkey->id==NULL || jkey->id->s==NULL) return -1; i = 0; *p = NULL; while(i < jwl->len) { lock_set_get(jwl->sems, i); if(jwl->workers[i].pid <= 0) { lock_set_release(jwl->sems, i); i++; continue; } if((*p = find234(jwl->workers[i].sip_ids, (void*)jkey, NULL)) != NULL) { lock_set_release(jwl->sems, i); #ifdef XJ_EXTRA_DEBUG LM_DBG("entry exists for <%.*s> in the" " pool of <%d> [%d]\n",jkey->id->len, jkey->id->s, jwl->workers[i].pid,i); #endif return jwl->workers[i].wpipe; } lock_set_release(jwl->sems, i); i++; } #ifdef XJ_EXTRA_DEBUG LM_DBG("entry does not exist for <%.*s>\n", jkey->id->len, jkey->id->s); #endif return -1; }
/** * return communication pipe with the worker that will process the message for * the id 'sid', or -1 if error * - jwl : pointer to the workers list * - sid : id of the entity (connection to Jabber - usually SHOULD be FROM * header of the incoming SIP message) * - p : will point to the SHM location of the 'sid' in jwl */ int xj_wlist_get(xj_wlist jwl, xj_jkey jkey, xj_jkey *p) { int i = 0, pos = -1, min = 100000; xj_jkey msid = NULL; if(jwl==NULL || jkey==NULL || jkey->id==NULL || jkey->id->s==NULL) return -1; *p = NULL; while(i < jwl->len) { lock_set_get(jwl->sems, i); if(jwl->workers[i].pid <= 0) { lock_set_release(jwl->sems, i); i++; continue; } if((*p = find234(jwl->workers[i].sip_ids, (void*)jkey, NULL))!=NULL) { if(pos >= 0) lock_set_release(jwl->sems, pos); lock_set_release(jwl->sems, i); #ifdef XJ_EXTRA_DEBUG LM_DBG("entry already exists for <%.*s> in the" " pool of <%d> [%d]\n",jkey->id->len, jkey->id->s, jwl->workers[i].pid,i); #endif return jwl->workers[i].wpipe; } if(min > jwl->workers[i].nr) { if(pos >= 0) lock_set_release(jwl->sems, pos); pos = i; min = jwl->workers[i].nr; } else lock_set_release(jwl->sems, i); i++; } if(pos >= 0 && jwl->workers[pos].nr < jwl->maxj) { jwl->workers[pos].nr++; msid = (xj_jkey)_M_SHM_MALLOC(sizeof(t_xj_jkey)); if(msid == NULL) goto error; msid->id = (str*)_M_SHM_MALLOC(sizeof(str)); if(msid->id == NULL) { _M_SHM_FREE(msid); goto error; } msid->id->s = (char*)_M_SHM_MALLOC(jkey->id->len); if(msid->id == NULL) { _M_SHM_FREE(msid->id); _M_SHM_FREE(msid); goto error; } if((*p = add234(jwl->workers[pos].sip_ids, msid)) != NULL) { msid->id->len = jkey->id->len; memcpy(msid->id->s, jkey->id->s, jkey->id->len); msid->hash = jkey->hash; msid->flag = XJ_FLAG_OPEN; lock_set_release(jwl->sems, pos); #ifdef XJ_EXTRA_DEBUG LM_DBG("new entry for <%.*s> in the pool of" " <%d> - [%d]\n", jkey->id->len, jkey->id->s, jwl->workers[pos].pid, pos); #endif return jwl->workers[pos].wpipe; } _M_SHM_FREE(msid->id->s); _M_SHM_FREE(msid->id); _M_SHM_FREE(msid); } error: if(pos >= 0) lock_set_release(jwl->sems, pos); LM_DBG("cannot create a new entry for <%.*s>\n", jkey->id->len, jkey->id->s); return -1; }
void ul_lock_idx(int idx) { lock_set_get(ul_locks, idx); }
void shvar_lock_idx(int idx) { lock_set_get(shvar_locks, idx); }
/** * SER2Jab connection management - function to use with iHttp module * - be aware of who is able to use the ihttp because he can close any * open connection between SER and Jabber server */ int xjab_connections(ih_req_p _irp, void *_p, char *_bb, int *_bl, char *_hb, int *_hl) { t_xj_jkey jkey, *p; str _u; ih_param_p _ipp = NULL; int idx, i, maxcount; char *cp; if(!_irp || !_bb || !_bl || *_bl <= 0 || !_hb || !_hl || *_hl <= 0) return -1; *_hl = 0; *_hb = 0; idx = -1; strcpy(_bb, "<h4>Active XMPP connections</h4>"); if(_irp->params) { strcat(_bb, "<br><b>Close action is alpha release!</b><br>"); _ipp = _irp->params; i = 0; while(_ipp) { switch(_ipp->name[0]) { case 'w': idx = 0; cp = _ipp->value; while(*cp && *cp>='0' && *cp<='9') { idx = idx*10 + *cp-'0'; cp++; } i++; break; case 'u': _u.s = _ipp->value; _u.len = strlen(_ipp->value); jkey.id = &_u; i++; break; case 'i': jkey.hash = 0; cp = _ipp->value; while(*cp && *cp>='0' && *cp<='9') { jkey.hash = jkey.hash*10 + *cp-'0'; cp++; } i++; break; } _ipp = _ipp->next; } if(i!=3 || idx < 0 || idx >= jwl->len) { strcat(_bb, "<br><b><i>Bad parameters!</i></b>\n"); } else { strcat(_bb, "<br><b><i>The connection of ["); strcat(_bb, _u.s); if(xj_wlist_set_flag(jwl, &jkey, XJ_FLAG_CLOSE) < 0) strcat(_bb, "] does not exist!</i></b>\n"); else strcat(_bb, "] was scheduled for closing!</i></b>\n"); } *_bl = strlen(_bb); return 0; } if(jwl!=NULL && jwl->len > 0 && jwl->workers!=NULL) { for(idx=0; idx<jwl->len; idx++) { strcat(_bb, "<br><b><i>Worker["); strcat(_bb, int2str(idx, NULL)); strcat(_bb, "]</i></b> pid="); strcat(_bb, int2str(jwl->workers[idx].pid, NULL)); strcat(_bb, " nr of jobs="); strcat(_bb, int2str(jwl->workers[idx].nr, NULL)); if(!jwl->workers[idx].sip_ids) continue; lock_set_get(jwl->sems, idx); maxcount = count234(jwl->workers[idx].sip_ids); for (i = 0; i < maxcount; i++) { p = (xj_jkey)index234(jwl->workers[idx].sip_ids, i); if(p == NULL) continue; strcat(_bb, "<br> "); strcat(_bb, int2str(i, NULL)); strcat(_bb, ". "); strcat(_bb, "<a href=\"xjabc?w="); strcat(_bb, int2str(idx, NULL)); strcat(_bb, "&i="); strcat(_bb, int2str(p->hash, NULL)); strcat(_bb, "&u="); strncat(_bb, p->id->s, p->id->len); strcat(_bb, "\">close</a>"); strcat(_bb, " "); strcat(_bb, int2str(p->hash, NULL)); strcat(_bb, " "); strncat(_bb, p->id->s, p->id->len); } lock_set_release(jwl->sems, idx); } } *_bl = strlen(_bb); return 0; }
static void broadcast_profiles(utime_t ticks, void *param) { #define REPL_PROF_TRYSEND() \ do { \ nr++; \ if (ret > repl_prof_buffer_th) { \ /* send the buffer */ \ if (nr) \ dlg_replicate_profiles(&packet); \ bin_reset_back_pointer(&packet); \ nr = 0; \ } \ } while (0) struct dlg_profile_table *profile; map_iterator_t it; unsigned int count; int i; int nr = 0; int ret; void **dst; str *value; bin_packet_t packet; if (bin_init(&packet, &prof_repl_cap, REPLICATION_DLG_PROFILE, BIN_VERSION, 0) < 0) { LM_ERR("cannot initiate bin buffer\n"); return; } for (profile = profiles; profile; profile = profile->next) { if (!(profile->repl_type&REPL_PROTOBIN)) continue; count = 0; if (!profile->has_value) { count = noval_get_local_count(profile); if ((ret = repl_prof_add(&packet, &profile->name, 0, NULL, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); } else { for (i = 0; i < profile->size; i++) { lock_set_get(profile->locks, i); if (map_first(profile->entries[i], &it) < 0) { LM_ERR("map does not exist\n"); goto next_entry; } while (iterator_is_valid(&it)) { dst = iterator_val(&it); if (!dst || !*dst) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_val; } value = iterator_key(&it); if (!value) { LM_ERR("cannot retrieve profile's key\n"); goto next_val; } count = prof_val_get_local_count(dst); if ((ret = repl_prof_add(&packet, &profile->name, 1, value, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); next_val: if (iterator_next(&it) < 0) break; } next_entry: lock_set_release(profile->locks, i); } } } goto done; error: LM_ERR("cannot add any more profiles in buffer\n"); bin_free_packet(&packet); done: /* check if there is anything else left to replicate */ if (nr) dlg_replicate_profiles(&packet); bin_free_packet(&packet); #undef REPL_PROF_TRYSEND }
void receive_prof_repl(bin_packet_t *packet) { time_t now; str name; str value; unsigned int counter; struct dlg_profile_table *profile; int has_value; int i; void **dst; prof_value_info_t *rp; repl_prof_count_t *destination; /* optimize profile search */ struct dlg_profile_table *old_profile = NULL; str old_name = {NULL,0}; if (!profile_repl_cluster) return; if (packet->type != REPLICATION_DLG_PROFILE) { LM_WARN("Invalid dialog binary packet command: %d (from node: %d in cluster: %d)\n", packet->type, packet->src_id, profile_repl_cluster); return; } now = time(0); //*repl_prof_dests[index].last_msg = now; for (;;) { if (bin_pop_str(packet ,&name) == 1) break; /* pop'ed all pipes */ /* check if the same profile was sent */ if (!old_profile || old_name.len != name.len || memcmp(name.s, old_name.s, name.len) != 0) { old_profile = get_dlg_profile(&name); if (!old_profile) LM_WARN("received unknown profile <%.*s> from node %d\n", name.len, name.s, packet->src_id); old_name = name; } profile = old_profile; if (bin_pop_int(packet, &has_value) < 0) { LM_ERR("cannot pop profile's has_value int\n"); return; } if (has_value) { if (!profile->has_value) { LM_WARN("The other end does not have a value for this profile:" "<%.*s> [node: %d]\n", profile->name.len, profile->name.s, packet->src_id); profile = NULL; } if (bin_pop_str(packet, &value)) { LM_ERR("cannot pop the value of the profile\n"); return; } } if (bin_pop_int(packet, &counter) < 0) { LM_ERR("cannot pop profile's counter\n"); return; } if (profile) { if (!profile->has_value) { lock_get(&profile->noval_repl_info->lock); destination = find_destination(profile->noval_repl_info, packet->src_id); if(destination == NULL){ lock_release(&profile->noval_repl_info->lock); return; } destination->counter = counter; destination->update = now; lock_release(&profile->noval_repl_info->lock); } else { /* XXX: hack to make sure we find the proper index */ i = core_hash(&value, NULL, profile->size); lock_set_get(profile->locks, i); /* if counter is 0 and we don't have it, don't try to create */ if (!counter) { dst = map_find(profile->entries[i], value); if (!dst) goto release; } else { dst = map_get(profile->entries[i], value); } if (!*dst) { rp = shm_malloc(sizeof(prof_value_info_t)); if (!rp) { LM_ERR("no more shm memory to allocate repl_prof_value\n"); goto release; } memset(rp, 0, sizeof(prof_value_info_t)); *dst = rp; } else { rp = (prof_value_info_t *) * dst; } if (!rp->noval) rp->noval = repl_prof_allocate(); if (rp->noval) { lock_release(&rp->noval->lock); destination = find_destination(rp->noval, packet->src_id); if (destination == NULL) { lock_release(&rp->noval->lock); lock_set_release(profile->locks, i); return; } destination->counter = counter; destination ->update = now; lock_release(&rp->noval->lock); } release: lock_set_release(profile->locks, i); } } } return; }
/*! * \brief SQL REPLACE implementation * \param _h structure representing database connection * \param _k key names * \param _v values of the keys * \param _n number of key=value pairs * \param _un number of keys to build the unique key, starting from first * \param _m mode - first update, then insert, or first insert, then update * \return 0 on success, negative on failure */ int db_postgres_replace(const db1_con_t* _h, const db_key_t* _k, const db_val_t* _v, const int _n, const int _un, const int _m) { unsigned int pos = 0; int i; if(_un > _n) { LM_ERR("number of columns for unique key is too high\n"); return -1; } if(_un > 0) { for(i=0; i<_un; i++) { if(!VAL_NULL(&_v[i])) { switch(VAL_TYPE(&_v[i])) { case DB1_INT: pos += VAL_UINT(&_v[i]); break; case DB1_STR: pos += get_hash1_raw((VAL_STR(&_v[i])).s, (VAL_STR(&_v[i])).len); break; case DB1_STRING: pos += get_hash1_raw(VAL_STRING(&_v[i]), strlen(VAL_STRING(&_v[i]))); break; default: break; } } } pos &= (_pg_lock_size-1); lock_set_get(_pg_lock_set, pos); if(db_postgres_update(_h, _k, 0, _v, _k + _un, _v + _un, _un, _n -_un)< 0) { LM_ERR("update failed\n"); lock_set_release(_pg_lock_set, pos); return -1; } if (db_postgres_affected_rows(_h) <= 0) { if(db_postgres_insert(_h, _k, _v, _n)< 0) { LM_ERR("insert failed\n"); lock_set_release(_pg_lock_set, pos); return -1; } LM_DBG("inserted new record in database table\n"); } else { LM_DBG("updated record in database table\n"); } lock_set_release(_pg_lock_set, pos); } else { if(db_postgres_insert(_h, _k, _v, _n)< 0) { LM_ERR("direct insert failed\n"); return -1; } LM_DBG("directly inserted new record in database table\n"); } return 0; }
static void dlg_replicated_profiles(struct receive_info *ri) { int index; time_t now; str name; str value; char *ip; unsigned short port; unsigned int counter; struct dlg_profile_table *profile; int has_value; int i; void **dst; repl_prof_value_t *rp; /* optimize profile search */ struct dlg_profile_table *old_profile = NULL; str old_name; /* match the server */ for (index = 0; index < repl_prof_dests_nr; index++) { if (su_cmp(&ri->src_su, &repl_prof_dests[index].to)) break; } if (index == repl_prof_dests_nr) { get_su_info(&ri->src_su.s, ip, port); LM_WARN("received bin packet from unknown source: %s:%hu\n", ip, port); return; } now = time(0); *repl_prof_dests[index].last_msg = now; for (;;) { if (bin_pop_str(&name) == 1) break; /* pop'ed all pipes */ /* check if the same profile was sent */ if (!old_profile || old_name.len != name.len || memcmp(name.s, old_name.s, name.len) != 0) { old_profile = get_dlg_profile(&name); if (!old_profile) { get_su_info(&ri->src_su.s, ip, port); LM_WARN("received unknown profile <%.*s> from %s:%hu\n", name.len, name.s, ip, port); } old_name = name; } profile = old_profile; if (bin_pop_int(&has_value) < 0) { LM_ERR("cannot pop profile's has_value int\n"); return; } if (has_value) { if (!profile->has_value) { get_su_info(&ri->src_su.s, ip, port); LM_WARN("The other end does not have a value for this profile:" "<%.*s> [%s:%hu]\n", profile->name.len, profile->name.s, ip, port); profile = NULL; } if (bin_pop_str(&value)) { LM_ERR("cannot pop the value of the profile\n"); return; } } if (bin_pop_int(&counter) < 0) { LM_ERR("cannot pop profile's counter\n"); return; } if (profile) { if (!profile->has_value) { lock_get(&profile->repl->lock); profile->repl->dsts[index].counter = counter; profile->repl->dsts[index].update = now; lock_release(&profile->repl->lock); } else { /* XXX: hack to make sure we find the proper index */ i = core_hash(&value, NULL, profile->size); lock_set_get(profile->locks, i); /* if counter is 0 and we don't have it, don't try to create */ if (!counter) { dst = map_find(profile->entries[i], value); if (!dst) goto release; } else { dst = map_get(profile->entries[i], value); } if (!*dst) { rp = shm_malloc(sizeof(repl_prof_value_t)); if (!rp) { LM_ERR("no more shm memory to allocate repl_prof_value\n"); goto release; } memset(rp, 0, sizeof(repl_prof_value_t)); *dst = rp; } else { rp = (repl_prof_value_t *)*dst; } if (!rp->noval) rp->noval = repl_prof_allocate(); if (rp->noval) { lock_release(&rp->noval->lock); rp->noval->dsts[index].counter = counter; rp->noval->dsts[index].update = now; lock_release(&rp->noval->lock); } release: lock_set_release(profile->locks, i); } } } return; }
static void repl_prof_utimer_f(utime_t ticks, void *param) { #define REPL_PROF_TRYSEND() \ do { \ nr++; \ if (ret > repl_prof_buffer_th) { \ /* send the buffer */ \ if (nr) { \ dlg_replicate_profiles(); \ LM_DBG("sent %d records\n", nr); \ } \ if (bin_init(&module_name, REPLICATION_DLG_PROFILE, BIN_VERSION) < 0) { \ LM_ERR("cannot initiate bin buffer\n"); \ return; \ } \ nr = 0; \ } \ } while (0) struct dlg_profile_table *profile; static str module_name = str_init("dialog"); map_iterator_t it; unsigned int count; int i; int nr = 0; int ret; void **dst; str *value; if (bin_init(&module_name, REPLICATION_DLG_PROFILE, BIN_VERSION) < 0) { LM_ERR("cannot initiate bin buffer\n"); return; } for (profile = profiles; profile; profile = profile->next) { count = 0; if (!profile->has_value) { for (i = 0; i < profile->size; i++) { lock_set_get(profile->locks, i); count += profile->counts[i]; lock_set_release(profile->locks, i); } if ((ret = repl_prof_add(&profile->name, 0, NULL, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); } else { for (i = 0; i < profile->size; i++) { lock_set_get(profile->locks, i); if (map_first(profile->entries[i], &it) < 0) { LM_ERR("map does not exist\n"); goto next_entry; } while (iterator_is_valid(&it)) { dst = iterator_val(&it); if (!dst || !*dst) { LM_ERR("[BUG] bogus map[%d] state\n", i); goto next_val; } value = iterator_key(&it); if (!value) { LM_ERR("cannot retrieve profile's key\n"); goto next_val; } count = repl_prof_get(dst); if ((ret = repl_prof_add(&profile->name, 1, value, count)) < 0) goto error; /* check if the profile should be sent */ REPL_PROF_TRYSEND(); next_val: if (iterator_next(&it) < 0) break; } next_entry: lock_set_release(profile->locks, i); } } } goto done; error: LM_ERR("cannot add any more profiles in buffer\n"); done: /* check if there is anything else left to replicate */ LM_DBG("sent %d records\n", nr); if (nr) dlg_replicate_profiles(); #undef REPL_PROF_TRYSEND }
/* locks a tree branch */ static inline void prv_lock_tree_branch(unsigned char b) { lock_set_get( root->entry_lock_set, root->entries[b].lock_idx); }
/*! * \brief Lock a lock with a certain index * \param idx lock index */ void subs_lock_idx(int idx) { lock_set_get(subs_locks, idx); }