Hy, 
I've had the problem that the at driver modem group config is read in a
verry unpleasent manner: it parses the whole config. in the original case, 
it parses the wohle config for every modem group it finds. this makes kannel
eat much cpu, and makes the at thread lock each other up on sartup.
(lets see, maybe you have 40 modem smsc's, 3 modem groups, original aproach 
reads and parses the config 120 times)

my first aproach was, to read the config once, and keep each entry inside a 
List.
ok, just parsing config 40 times for our example above. gives a lot of 
performance, 
but still makes kannel behave funny on startup, depending on the number of 
modems, 
you might get a status page for the first time several minutes after kannel is 
started.
it's done faster, but still blasts cpu to the limit. (even if you restart a 
dead modem)

my actual solution reaches out a bit deeper into bearerbox, and looks this way: 

in bb_smscconn.c:
Global:
List *modem_definitions;

in int smsc2_start(Cfg *cfg):

+       modem_definitions=at4_read_modems(cfg);

    for (i = 0; i < gwlist_len(smsc_groups) && 
        (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
        conn = smscconn_create(grp, 1); 
        if (conn == NULL)
            panic(0, "Cannot start with SMSC connection failing");
        gwlist_append(smsc_list, conn);
    }


in smscconn.c:
Global:
extern List *modem_definitions;

in SMSCConn *smscconn_create(CfgGroup *grp, int start_as_stopped):

        ret = smsc_smpp_create(conn, grp);
    else if (octstr_compare(smsc_type, octstr_imm("at4")) == 0){
+               if (modem_definitions==NULL)
+                       panic(0, "AT4[-]: AT4 requires modem groups. none 
found.  ");
+               ret = smsc_at4_create(conn,grp,gwlist_copy(modem_definitions, 
at4_copy_modem));
        }
    else if (octstr_compare(smsc_type, octstr_imm("cgw")) == 0)

in the at driver there's something like that:
List *at4_read_modems(Cfg *cfg)
{
    List *grplist;
    CfgGroup *grp;
        Octstr *cmtinum;
        Octstr *id=NULL;
    at4_ModemDef *modem;
        List *modems=NULL;

    grplist = cfg_get_multi_group(cfg, octstr_imm("modems"));
    if (grplist == NULL){
        info(0, "we have no modem definitions.");
                return modems;
        }
        else
                debug("bb.smsc.at4", 0, "AT4[]: Found <%ld> modems in config",
                          gwlist_len(grplist));


    grp = NULL;
    while (grplist && (grp = gwlist_extract_first(grplist)) != NULL) {
        id = cfg_get(grp, octstr_imm("id"));
        if (id == NULL) {
            error(0, "Modems group without id, bad");
                }
                else {
                        modem = gw_malloc(sizeof(at4_ModemDef));
                        long resetIndex = -1;
                        
                        if (modems==NULL) modems=gwlist_create();
                        gwlist_append(modems, modem);
                        modem->id = cfg_get(grp, octstr_imm("id"));
*snip*
                        cfg_get_integer(&modem->enable_me_callerid, grp, 
octstr_imm("callerid-autodetect"));
                        grp = NULL;
                }
        O_DESTROY(id);
    }
        
        if (grplist != NULL)
                gwlist_destroy(grplist, NULL);
        return modems;
}



and:
void *at4_copy_modem(const void *copymodem)
{
    at4_ModemDef *modem;
        at4_ModemDef *param=(at4_ModemDef*)copymodem;

        modem = gw_malloc(sizeof(at4_ModemDef));
                        
#define O_COPY(var) if (param->var!=NULL) 
modem->var=octstr_duplicate(param->var); else modem->var=NULL
#define COPY_VAR(var) modem->var=param->var
        O_COPY(id);
*snip*
}

which is called at the config parse function through a list iterator.

I'm aware that this bends the bearerbox/smsc-interface. but is there another 
smarter way to do so? to have it just parse the configs once?

btw, with this way the kannel status page is allmost instant responsible.

Wilfried Goesgens

Reply via email to