Skip to content

Commit

Permalink
Merge pull request #781 from ionutrazvanionita/dlg_profiles
Browse files Browse the repository at this point in the history
[dialog] flag for replicating profiles
  • Loading branch information
Ionut Ionita committed Feb 25, 2016
2 parents a547af5 + 6a4f732 commit 2b8fd2d
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 188 deletions.
15 changes: 10 additions & 5 deletions modules/dialog/README
Expand Up @@ -788,25 +788,30 @@ modparam("dialog", "flags_column", "flags_c_name")

1.6.36. profiles_with_value (string)

List of names for profiles with values.
List of names for profiles with values. Flag /b allows
replicating dialogs over the bin interface. Before, all of them
were replicated.

Default value is “empty”.

Example 1.36. Set profiles_with_value parameter
...
modparam("dialog", "profiles_with_value", "caller ; my_profile; share/s"
)
modparam("dialog", "profiles_with_value", "caller ; my_profile; share/s;
repl/b;")
...

1.6.37. profiles_no_value (string)

List of names for profiles without values.
List of names for profiles without values. Flag /b allows
replicating dialogs over the bin interface. Before, all of them
were replicated.

Default value is “empty”.

Example 1.37. Set profiles_no_value parameter
...
modparam("dialog", "profiles_no_value", "inbound ; outbound ; shared/s")
modparam("dialog", "profiles_no_value", "inbound ; outbound ; shared/s;
repl/b;")
...

1.6.38. db_flush_vals_profiles (int)
Expand Down
21 changes: 13 additions & 8 deletions modules/dialog/dlg_db_handler.c
Expand Up @@ -388,7 +388,7 @@ void read_dialog_profiles(char *b, int l, struct dlg_cell *dlg,int double_check,
char *end;
char *p,*s,*e;
char bk;
int use_cached;
unsigned repl_type;

end = b + l;
p = b;
Expand All @@ -402,7 +402,7 @@ void read_dialog_profiles(char *b, int l, struct dlg_cell *dlg,int double_check,

if (double_check) {
LM_DBG("Double checking profile - if it exists we'll skip it \n");
use_cached = 0;
repl_type = REPL_NONE;

/* check if this is a shared profile, and remove /s for manual
* matching */
Expand All @@ -416,11 +416,13 @@ void read_dialog_profiles(char *b, int l, struct dlg_cell *dlg,int double_check,
/* skip spaces after p */
for (++s; *s == ' ' && s < e; s++);
if ( s < e && *s == 's')
use_cached=1;
repl_type = REPL_CACHEDB;
else if (s < e && *s == 'b')
repl_type = REPL_PROTOBIN;
}

for (it=dlg->profile_links;it;it=it->next) {
if (it->profile->use_cached == use_cached &&
if (it->profile->repl_type == repl_type &&
it->profile->name.len == double_check_name.len &&
memcmp(it->profile->name.s,double_check_name.s,
double_check_name.len) == 0) {
Expand Down Expand Up @@ -1161,7 +1163,7 @@ str* write_dialog_vars( struct dlg_val *vars)
* deallocated if the dialog ends */
str* write_dialog_profiles( struct dlg_profile_link *links)
{
static str o = {NULL,0},cached_marker={"/s",2};
static str o = {NULL,0},cached_marker={"/s",2}, bin_marker={"/b", 2};
static int o_l = 0;
struct dlg_profile_link *link;
unsigned int l,i;
Expand All @@ -1176,8 +1178,8 @@ str* write_dialog_profiles( struct dlg_profile_link *links)
for( i=0 ; i<link->value.len ; i++ )
if (link->value.s[i]=='|' || link->value.s[i]=='#'
|| link->value.s[i]=='\\') l++;
if (link->profile->use_cached)
l+=cached_marker.len;
if (link->profile->repl_type!=REPL_NONE/*==(CACHEDB||PROTOBIN)*/)
l+=cached_marker.len; /* same length for both */
}

/* allocate the string to be stored */
Expand All @@ -1195,9 +1197,12 @@ str* write_dialog_profiles( struct dlg_profile_link *links)
o.len = l;
p = o.s;
for ( link=links; link ; link=link->next) {
if (link->profile->use_cached)
if (link->profile->repl_type == REPL_CACHEDB)
p += write_pair( p, &link->profile->name, &cached_marker,
&link->value);
else if (link->profile->repl_type == REPL_PROTOBIN)
p += write_pair( p, &link->profile->name, &bin_marker,
&link->value);
else
p += write_pair( p, &link->profile->name, NULL, &link->value);
}
Expand Down
92 changes: 64 additions & 28 deletions modules/dialog/dlg_profile.c
Expand Up @@ -47,7 +47,7 @@ static int finished_allocating_locks = 0;
extern int log_profile_hash_size;

static struct dlg_profile_table* new_dlg_profile( str *name,
unsigned int size, unsigned int has_value, unsigned use_cached);
unsigned int size, unsigned int has_value, unsigned repl_type);

/* used by cachedb interface */
static cachedb_funcs cdbf;
Expand Down Expand Up @@ -145,14 +145,16 @@ int add_profile_definitions( char* profiles, unsigned int has_value)
char *d;
char *e;
str name;
unsigned int i, use_cached = 0;

unsigned int i;
enum repl_types type;
if (profiles==NULL || strlen(profiles)==0 )
return 0;

p = profiles;
do {
use_cached = 0;
/* By default no replication (no CACHEDB nor BIN)*/
type = REPL_NONE;

/* locate name of profile */
name.s = p;
d = strchr( p, ';');
Expand Down Expand Up @@ -181,13 +183,29 @@ int add_profile_definitions( char* profiles, unsigned int has_value)
for (++p; *p == ' ' && p < e; p++);
if ( p < e && *p == 's') {
if (cdb_url.len && cdb_url.s) {
use_cached = 1;
if (type==REPL_PROTOBIN)
goto repl_error;

type= REPL_CACHEDB;
} else {
LM_WARN("profile %.*s configured to be stored in CacheDB, "
"but the cachedb_url was not defined\n",
name.len, name.s);
use_cached = 0;
}
} else if ( p < e && *p == 'b') {
if (profile_replicate_cluster) {
if (type==REPL_CACHEDB)
goto repl_error;

type = REPL_PROTOBIN;
} else {
LM_WARN("profile %.*s configured to be replicated over BIN, "
"but replicate_profiles_to param is not defined\n",
name.len, name.s);
}
} else if (isalnum(*p)) {
LM_ERR("Invalid letter in profile definitition </%c>!\n", *p);
return -1;
}
}

Expand All @@ -202,17 +220,22 @@ int add_profile_definitions( char* profiles, unsigned int has_value)

/* name ok -> create the profile */
LM_DBG("creating profile <%.*s> %s\n", name.len, name.s,
use_cached ? "cached" : "");
type ==REPL_CACHEDB ? "cached" :
(type==REPL_PROTOBIN ? "bin replicated": ""));

if (new_dlg_profile( &name, 1 << log_profile_hash_size,
has_value, use_cached)==NULL) {
has_value, type)==NULL) {
LM_ERR("failed to create new profile <%.*s>\n",name.len,name.s);
return -1;
}

}while( (p=d)!=NULL );

return 0;

repl_error:
LM_ERR("Can't use both bin replication and cachedb!\n");
return -1;
}

#define DLG_COPY(_d, _s) \
Expand Down Expand Up @@ -393,7 +416,7 @@ struct dlg_profile_table* search_dlg_profile(str *name)
{
struct dlg_profile_table *profile;
char *p,*e;
int use_cached=0;
unsigned repl_type=REPL_NONE;
str profile_name = *name;

/* check if this is a shared profile, and remove /s for lookup */
Expand All @@ -406,11 +429,14 @@ struct dlg_profile_table* search_dlg_profile(str *name)
/* skip spaces after p */
for (++p; *p == ' ' && p < e; p++);
if ( p < e && *p == 's')
use_cached=1;
repl_type=REPL_CACHEDB;
else if (p < e && *p == 'b')
repl_type=REPL_PROTOBIN;
}

for( profile=profiles ; profile ; profile=profile->next ) {
if (profile->use_cached == use_cached && profile_name.len ==profile->name.len &&
if (profile->repl_type == repl_type &&
profile_name.len ==profile->name.len &&
memcmp(profile_name.s,profile->name.s,profile_name.len)==0 )
return profile;
}
Expand All @@ -419,7 +445,7 @@ struct dlg_profile_table* search_dlg_profile(str *name)
}

static struct dlg_profile_table* new_dlg_profile( str *name, unsigned int size,
unsigned int has_value, unsigned use_cached)
unsigned int has_value, unsigned repl_type)
{
struct dlg_profile_table *profile;
struct dlg_profile_table *ptmp;
Expand All @@ -446,9 +472,10 @@ static struct dlg_profile_table* new_dlg_profile( str *name, unsigned int size,
return NULL;
}

len = sizeof(struct dlg_profile_table) + name->len + 1 +
(!use_cached ? (size * ( (has_value == 0 ) ?
sizeof( int ) : sizeof( map_t ) )) : 0);
len = sizeof(struct dlg_profile_table) + name->len + 1;
/* anything else than only CACHEDB */
if (repl_type != REPL_CACHEDB)
len += size * ((has_value==0) ? sizeof(int):sizeof(map_t));

profile = (struct dlg_profile_table *)shm_malloc(len);

Expand All @@ -463,12 +490,10 @@ static struct dlg_profile_table* new_dlg_profile( str *name, unsigned int size,

profile->size = size;
profile->has_value = (has_value==0)?0:1;
profile->use_cached = use_cached;

profile->repl = NULL;
profile->repl_type = repl_type;

/* init locks */
if (!use_cached) {
if (repl_type != REPL_CACHEDB) {
profile->locks = get_a_lock_set(size) ;

if( !profile->locks )
Expand All @@ -479,7 +504,7 @@ static struct dlg_profile_table* new_dlg_profile( str *name, unsigned int size,
}
}

if( use_cached ) {
if( repl_type == REPL_CACHEDB ) {

profile->name.s = (char *)(profile + 1);

Expand Down Expand Up @@ -531,7 +556,7 @@ static void destroy_dlg_profile(struct dlg_profile_table *profile)

if (profile==NULL)
return;
if( profile -> has_value && !profile -> use_cached )
if( profile->has_value && !(profile->repl_type==REPL_CACHEDB) )
{
for( i= 0; i < profile->size; i++)
map_destroy( profile->entries[i], free_profile_val);
Expand Down Expand Up @@ -571,7 +596,7 @@ void destroy_linkers(struct dlg_profile_link *linker, char is_replicated)
/* unlink from profile table */


if (!l->profile->use_cached) {
if (!(l->profile->repl_type==REPL_CACHEDB)) {
lock_set_get( l->profile->locks, l->hash_idx);

if( l->profile->has_value)
Expand Down Expand Up @@ -675,7 +700,7 @@ static void link_dlg_profile(struct dlg_profile_link *linker,

/* insert into profile hash table */
/* but only if cachedb is not used */
if (!linker->profile->use_cached) {
if (!(linker->profile->repl_type==REPL_CACHEDB)) {
/* calculate the hash position */
hash = calc_hash_profile(&linker->value, dlg, linker->profile);
linker->hash_idx = hash;
Expand Down Expand Up @@ -870,7 +895,7 @@ unsigned int get_profile_size(struct dlg_profile_table *profile, str *value)
{
/* iterate through the hash and count all records */

if (cdbc && profile->use_cached) {
if (cdbc && (profile->repl_type == REPL_CACHEDB)) {
if (dlg_fill_name(&profile->name) < 0)
goto failed;

Expand Down Expand Up @@ -902,7 +927,7 @@ unsigned int get_profile_size(struct dlg_profile_table *profile, str *value)

if( value==NULL )
{
if (cdbc && profile->use_cached) {
if (cdbc && (profile->repl_type == REPL_CACHEDB)) {
if (dlg_fill_size(&profile->name) < 0)
goto failed;

Expand Down Expand Up @@ -932,7 +957,7 @@ unsigned int get_profile_size(struct dlg_profile_table *profile, str *value)
}
else
{
if (cdbc && profile->use_cached) {
if (cdbc && (profile->repl_type == REPL_CACHEDB)) {
if (dlg_fill_value(&profile->name, value) < 0)
goto failed;

Expand Down Expand Up @@ -1039,7 +1064,7 @@ struct mi_root * mi_get_profile(struct mi_root *cmd_tree, void *param )
goto error;
}

if (profile->use_cached) {
if (profile->repl_type == REPL_CACHEDB) {
attr = add_mi_attr(node, MI_DUP_VALUE, "shared", 6, "yes", 3);
} else {
attr = add_mi_attr(node, MI_DUP_VALUE, "shared", 6, "no", 2);
Expand All @@ -1048,6 +1073,17 @@ struct mi_root * mi_get_profile(struct mi_root *cmd_tree, void *param )
goto error;
}

if (profile->repl_type == REPL_PROTOBIN) {
attr = add_mi_attr(node, MI_DUP_VALUE, "replicated", 10, "yes", 3);
} else {
attr = add_mi_attr(node, MI_DUP_VALUE, "replicated", 10, "no", 2);
}
if (attr == NULL) {
goto error;
}



return rpl_tree;
error:
free_mi_tree(rpl_tree);
Expand Down Expand Up @@ -1104,7 +1140,7 @@ struct mi_root * mi_get_profile_values(struct mi_root *cmd_tree, void *param )
profile = search_dlg_profile( profile_name );
if (profile==NULL)
return init_mi_tree( 404, MI_SSTR("Profile not found"));
if (profile->use_cached)
if (profile->repl_type == REPL_CACHEDB)
return init_mi_tree( 405, MI_SSTR("Unsupported command for shared profiles"));

/* gather dialog count for all values in this profile */
Expand Down
4 changes: 3 additions & 1 deletion modules/dialog/dlg_profile.h
Expand Up @@ -54,10 +54,11 @@ struct dlg_profile_link {

struct repl_prof_novalue;

enum repl_types {REPL_NONE=0, REPL_CACHEDB=1, REPL_PROTOBIN};
struct dlg_profile_table {
str name;
unsigned int has_value;
unsigned int use_cached;
enum repl_types repl_type;


unsigned int size;
Expand Down Expand Up @@ -146,6 +147,7 @@ extern str cdb_noval_prefix;
extern str cdb_size_prefix;
extern str cdb_url;
extern int profile_timeout;
extern int profile_replicate_cluster;

extern struct dlg_profile_table *profiles;

Expand Down

5 comments on commit 2b8fd2d

@46labs
Copy link

@46labs 46labs commented on 2b8fd2d Feb 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So going forward, to replicate dialogs over the binary interface, you must throw the /b flag in modparam?

@ionutrazvanionita
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@46labs yes. /s for cachedb sharing, /b for sharing through binary interface. If no flag set, profile is not replicated. Also you can't do both cachedb and binary interface replication, simply because it makes no sense.

@46labs
Copy link

@46labs 46labs commented on 2b8fd2d Mar 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you need to specify the /b both in the modparam as well as the script? An error is thrown if the profile name doesnt match the profile name in the modparam...so if a profile named "calls" was previously in the modparam, then it needs to be changed to calls/b and the script also needs to be changed to calls/b? Ie you cannot have calls/b in the modparam and just calls in the script.

If that is the case, then it can break all kinds of external scripts that rely on consistent profile names, and also requires that you update an entire cluster of servers at a time to effect this change.

@ionutrazvanionita
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. That is the logic behind the profiles, didn't want to change that. The same story is if you use '/b' for a profile. Perhaps that shall be changed in the future.

@46labs
Copy link

@46labs 46labs commented on 2b8fd2d Mar 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ionut,

Right, but this requires all cluster members to be running at least the same source. If any programs are written that parse profile names external to opensips (either through fifo or http interface) have to be rewritten to handle the change. Can the flag not be thrown in modparam only? Or, what would also be suitable would be to throw a flag in modparam that makes all profiles either use /s or /b?

Please sign in to comment.