From 6ca781b8a38474ab428d5fcb3b489dfe3e974334 Mon Sep 17 00:00:00 2001 From: bustico Date: Fri, 21 Mar 2008 09:03:34 +0000 Subject: - numerous fixes - socket in non blocking mode (resolve some deadlock, and agent are immune to another agent beeing blocked) --- src/ivy.c | 571 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 385 insertions(+), 186 deletions(-) (limited to 'src/ivy.c') diff --git a/src/ivy.c b/src/ivy.c index df180b2..1cae380 100644 --- a/src/ivy.c +++ b/src/ivy.c @@ -16,13 +16,12 @@ */ /* - TODO : ° version non bloquante - ° outil de chasse aux memleak - ° mesures de perfo - ° compil rejeu en monothread et omp et tests - ° compil sur mac et windows pour portabilité + TODO : ° compil sur mac ° faire un repertoire exemple avec tous les executables + ° commit svn (penser aux fichiers nouveaux, et deplacés) + ° compil sur windows ° faire un configure + ° mettre à jour la doc / site web */ #ifdef OPENMP @@ -41,10 +40,11 @@ #include #include - - #include + +#include "version.h" +#include "param.h" #include "uthash.h" #include "intervalRegexp.h" #include "ivychannel.h" @@ -55,10 +55,6 @@ #include "ivybind.h" #include "ivy.h" -#define VERSION 3 - -#define MAX_MATCHING_ARGS 40 - #define ARG_START "\002" #define ARG_END "\003" @@ -69,7 +65,7 @@ * effectuée si on stringifie directement dans la macro GenerateIvyBus */ #define str(bus) #bus #define GenerateIvyBus(domain,bus) str(domain)":"str(bus) -static char* DefaultIvyBus = GenerateIvyBus(DEFAULT_DOMAIN,DEFAULT_BUS); +static char* DefaultIvyBus = GenerateIvyBus(DEFAULT_DOMAIN,IVY_DEFAULT_BUS); typedef enum { Bye, /* l'application emettrice se termine */ @@ -86,14 +82,14 @@ typedef enum { } MsgType; -typedef struct _global_reg_lst *GlobRegPtr; typedef struct _msg_snd_dict *MsgSndDictPtr; +typedef struct _global_reg_lst *GlobRegPtr; struct _msg_rcv { /* requete d'emission d'un client */ MsgRcvPtr next; int id; - const char *regexp; /* regexp du message a recevoir */ + char *regexp; /* regexp du message a recevoir */ MsgCallback callback; /* callback a declancher a la reception */ void *user_data; /* stokage d'info client */ }; @@ -121,11 +117,12 @@ struct _msg_snd_dict { /* requete de reception d'un client */ struct _clnt_lst_dict { IvyClientPtr next; Client client; /* la socket client */ + char *app_name; /* nom de l'application */ unsigned short app_port; /* port de l'application */ int id; /* l'id n'est pas liée uniquement - a la regexp, mais au couple - regexp, client */ + a la regexp, mais au couple + regexp, client */ GlobRegPtr srcRegList; /* liste de regexp source */ #ifdef OPENMP int endRegexpReceived; @@ -190,17 +187,18 @@ static void freeClient ( IvyClientPtr client); static void delOneClient (const Client client); static void delRegexpForOneClientFromDictionary (const char *regexp, const IvyClientPtr client); +static void delOneIvyClientFromDictionaryEntry (MsgSndDictPtr msgSendDict, + const IvyClientPtr client); +static void delOneClientFromDictionaryEntry (MsgSndDictPtr msgSendDict, + const Client client); static void delAllRegexpsFromDictionary (); -static void addRegexpToDictionary (const char* regexp, IvyClientPtr client, int id, - IvyBinding bind); -static void changeRegexpInDictionary (const char* regexp, IvyClientPtr client, int id, - IvyBinding bind); - -static char delRegexpForOneClient (const char *regexp, const IvyClientPtr client, int id); -static void addRegexp (const char* regexp, IvyClientPtr client, int id, - IvyBinding bind); -static void changeRegexp (const char* regexp, IvyClientPtr client, int id, IvyBinding bind); -static void addOrChangeRegexp (const char* regexp, IvyClientPtr client, int id, IvyBinding bind); +static void addRegexpToDictionary (const char* regexp, IvyClientPtr client); +static void changeRegexpInDictionary (const char* regexp, IvyClientPtr client); + +static char delRegexpForOneClient (const IvyClientPtr client, int id); +static void addRegexp (const char* regexp, IvyClientPtr client); +static void changeRegexp (const char* regexp, IvyClientPtr client); +static void addOrChangeRegexp (const char* regexp, IvyClientPtr client); static int IvyCheckBuffer( const char* buffer ); #ifdef OPENMP @@ -233,9 +231,48 @@ static char * nextArg( char *s, const char *separator ) if ( end == start ) return NULL; return start; } -static int MsgSendTo( Client client, MsgType msgtype, int id, const char *message ) + +static SendState MsgSendTo(IvyClientPtr ivyClient, + MsgType msgtype, int id, const char *message ) { - return SocketSend( client, "%d %d" ARG_START "%s\n", msgtype, id, message); + SendState state = + SocketSend( ivyClient->client, "%d %d" ARG_START "%s\n", msgtype, id, message); + + if ((application_callback != NULL) && (ivyClient != NULL)) { + switch (state) { + case SendStateChangeToCongestion : + (*application_callback) (ivyClient, application_user_data, + IvyApplicationCongestion); +#ifdef DEBUG + { + char *remotehost; + unsigned short remoteport; + /* probably bogus call, but this is for debug only anyway */ + SocketGetRemoteHost( ivyClient->client, &remotehost, &remoteport ); + TRACE("Congestion de %s:%hu\n", remotehost, remoteport ); + } +#endif + break; + + case SendStateFifoFull : + (*application_callback) (ivyClient, application_user_data, + IvyApplicationFifoFull); +#ifdef DEBUG + { + char *remotehost; + unsigned short remoteport; + /* probably bogus call, but this is for debug only anyway */ + SocketGetRemoteHost( ivyClient->client, &remotehost, &remoteport ); + TRACE("Fifo pleine pour %s:%hu, les messages seront perdus\n", remotehost, remoteport ); + } +#endif + break; + + default: + break; + } + } + return (state); } static void IvyCleanup() @@ -248,7 +285,7 @@ static void IvyCleanup() IVY_LIST_EACH_SAFE( allClients, clnt, next ) { /* on dit au revoir */ - MsgSendTo( clnt->client, Bye, 0, "" ); + MsgSendTo( clnt, Bye, 0, "" ); SocketClose( clnt->client ); IVY_LIST_EACH (clnt->srcRegList, regLst) { if (regLst->str_regexp != NULL) { @@ -297,7 +334,7 @@ RegexpCall (const MsgSndDictPtr msg, const char * const message) static IvyBuffer bufferArg = {NULL, 0, 0}; char bufferId[16]; int match_count ; - int waiting ; + SendState state; int indx; int arglen; const char *arg; @@ -314,7 +351,6 @@ RegexpCall (const MsgSndDictPtr msg, const char * const message) #endif // OPENMP match_count = 0; - waiting = 0; rc= IvyBindingExec(msg->binding, message ); if (rc<1) return 0; /* no match */ @@ -339,10 +375,43 @@ RegexpCall (const MsgSndDictPtr msg, const char * const message) IVY_LIST_EACH(msg->clientList, clnt ) { sprintf (bufferId, "%d %d" ARG_START ,Msg, clnt->id); - waiting = SocketSendRawWithId(clnt->client, bufferId, bufferArg.data , bufferArg.offset); + state = SocketSendRawWithId(clnt->client, bufferId, bufferArg.data , bufferArg.offset); match_count++; - if ( waiting ) - fprintf(stderr, "Ivy: Slow client : %s\n", clnt->app_name ); + + if (application_callback != NULL) { + switch (state) { + case SendStateChangeToCongestion : + (*application_callback) (clnt, application_user_data, + IvyApplicationCongestion); +#ifdef DEBUG + { + char *remotehost; + unsigned short remoteport; + /* probably bogus call, but this is for debug only anyway */ + SocketGetRemoteHost( clnt->client, &remotehost, &remoteport ); + TRACE("Congestion de %s:%hu\n", remotehost, remoteport ); + } +#endif + break; + + case SendStateFifoFull : + (*application_callback) (clnt, application_user_data, + IvyApplicationFifoFull); +#ifdef DEBUG + { + char *remotehost; + unsigned short remoteport; + /* probably bogus call, but this is for debug only anyway */ + SocketGetRemoteHost( clnt->client, &remotehost, &remoteport ); + TRACE("Fifo pleine pour %s:%hu, les messages seront perdus\n", remotehost, remoteport ); + } +#endif + break; + + default: + break; + } + } } return match_count; } @@ -354,7 +423,7 @@ RegexpCallUnique (const MsgSndDictPtr msg, const char * const message, const static IvyBuffer bufferArg = {NULL, 0, 0}; char bufferId[16]; int match_count ; - int waiting ; + SendState state; int indx; int arglen; const char *arg; @@ -362,7 +431,6 @@ RegexpCallUnique (const MsgSndDictPtr msg, const char * const message, const int rc; match_count = 0; - waiting = 0; rc= IvyBindingExec(msg->binding, message ); if (rc<1) return 0; /* no match */ @@ -389,47 +457,51 @@ RegexpCallUnique (const MsgSndDictPtr msg, const char * const message, const if (clientUnique != clnt->client) continue; sprintf (bufferId, "%d %d" ARG_START ,Msg, clnt->id); - waiting = SocketSendRawWithId(clnt->client, bufferId, bufferArg.data , bufferArg.offset); + state = SocketSendRawWithId(clnt->client, bufferId, bufferArg.data , bufferArg.offset); match_count++; - if ( waiting ) - fprintf(stderr, "Ivy: Slow client : %s\n", clnt->app_name ); + + if (( state == SendStateChangeToCongestion ) && (application_callback != NULL)) { + (*application_callback)( clnt, application_user_data, IvyApplicationCongestion ); + } } + return match_count; } - -static int CheckConnected( IvyClientPtr clnt ) +static int CheckConnected( Client sclnt ) { - IvyClientPtr client; - struct in_addr *addr1; - struct in_addr *addr2; - - if ( clnt->app_port == 0 ) /* Old Ivy Protocol Dont check */ - return 0; - /* recherche dans la liste des clients de la presence de clnt */ - IVY_LIST_EACH( allClients, client ) - { - /* client different mais port identique */ - if ( (client != clnt) && (clnt->app_port == client->app_port) ) - { - /* et meme machine */ - addr1 = SocketGetRemoteAddr( client->client ); - addr2 = SocketGetRemoteAddr( clnt->client ); - if ( addr1->s_addr == addr2->s_addr ) - return 1; - } - /* client different mais applicationID identique */ - /* TODO est-ce utile ??? verif dans UDP - if ( (client != clnt) && (clnt->app_id == client->app_id) ) - { - return 1; - } - */ - + IvyClientPtr iclient; + struct in_addr *addr1; + struct in_addr *addr2; + char *remotehost; + unsigned short remoteport; + + SocketGetRemoteHost( sclnt, &remotehost, &remoteport ); + + if ( remoteport == 0 ) /* Old Ivy Protocol Dont check */ + return 0; + + IVY_LIST_EACH( allClients, iclient ) + { + /* client different mais port identique */ + if ((iclient->client != sclnt) && (remoteport == iclient->app_port)) { + /* et meme machine */ + addr1 = SocketGetRemoteAddr( iclient->client ); + addr2 = SocketGetRemoteAddr( sclnt ); + if ( addr1->s_addr == addr2->s_addr ) { + TRACE ("DBG> CheckConnected " + "clnt->app_uuid[%s] et iclient->app_uuid[%s] %s\n", + SocketGetUuid (sclnt), + iclient->app_name, + SocketGetUuid (iclient->client)); + return 1; } - return 0; + } + } + + return 0; } @@ -443,23 +515,22 @@ static void Receive( Client client, void *data, char *line ) char *argv[MAX_MATCHING_ARGS]; char *arg; int kind_of_msg = Bye; - IvyBinding ivyBind; - - const char *errbuf; - int erroffset; + clnt = (IvyClientPtr)data; err = sscanf( line ,"%d %d", &kind_of_msg, &id ); arg = strstr( line , ARG_START ); if ( (err != 2) || (arg == 0) ) { - printf("Quitting bad format %s\n", line); - MsgSendTo( client, Error, Error, "bad format request expected 'type id ...'" ); - MsgSendTo( client, Bye, 0, "" ); - SocketClose( client ); - return; + clnt->client= client; + printf("Quitting bad format %s\n", line); + MsgSendTo(clnt, Error, Error, "bad format request expected " + "'type id ...'" ); + MsgSendTo(clnt, Bye, 0, "" ); + SocketClose( client ); + return; } arg++; - clnt = (IvyClientPtr)data; + clnt->id = id; switch( kind_of_msg ) { case Bye: @@ -488,19 +559,12 @@ static void Receive( Client client, void *data, char *line ) return; } - ivyBind = IvyBindingCompile( arg, & erroffset, & errbuf ); - if ( ivyBind != NULL ) { - addOrChangeRegexp (arg, clnt, id, ivyBind); - } else { - printf("Error compiling '%s', %s\n", arg, errbuf); - MsgSendTo( client, Error, erroffset, errbuf ); - } - + addOrChangeRegexp (arg, clnt); break; case DelRegexp: TRACE("Regexp Delete id=%d\n", id); - if (delRegexpForOneClient (arg, clnt, id)) { + if (delRegexpForOneClient (clnt, id)) { if ( application_bind_callback ) { (*application_bind_callback)( clnt, application_bind_data, id, arg, IvyRemoveBind ); @@ -517,10 +581,11 @@ static void Receive( Client client, void *data, char *line ) clnt->app_name = strdup( arg ); clnt->app_port = id; - if ( CheckConnected( clnt ) ) + if ( CheckConnected( clnt->client ) ) { - TRACE("Quitting already connected %s\n", line); + TRACE("Quitting already connected %s\n", line); + printf("Receive StartRegexp: Quitting already connected %s\n", line); IvySendError( clnt, 0, "Application already connected" ); SocketClose( client ); @@ -588,7 +653,7 @@ static void Receive( Client client, void *data, char *line ) case Ping: TRACE("Ping Message\n"); - MsgSendTo( client, Pong, id, "" ); + MsgSendTo(clnt, Pong, id, "" ); break; case Pong: @@ -612,12 +677,12 @@ static IvyClientPtr SendService( Client client, const char *appname ) clnt->client = client; clnt->app_name = strdup(appname); clnt->app_port = 0; - MsgSendTo( client, StartRegexp, ApplicationPort, ApplicationName); + MsgSendTo(clnt, StartRegexp, ApplicationPort, ApplicationName); IVY_LIST_EACH(msg_recv, msg ) { - MsgSendTo( client, AddRegexp,msg->id,msg->regexp); + MsgSendTo(clnt, AddRegexp,msg->id,msg->regexp); } - MsgSendTo( client, EndRegexp, 0, ""); + MsgSendTo(clnt, EndRegexp, 0, ""); IVY_LIST_ADD_END( allClients, clnt ) //printf ("DBG> SendService addAllClient: name=%s; client->client=%p\n", appname, clnt->client); @@ -646,26 +711,62 @@ static void ClientDelete( Client client, void *data ) delOneClient (client); } +static void ClientDecongestion ( Client client, void *data ) +{ + IvyClientPtr clnt; + +#ifdef DEBUG + char *remotehost; + unsigned short remoteport; +#endif + clnt = (IvyClientPtr)data; + if ( application_callback ) { + (*application_callback)( clnt, application_user_data, IvyApplicationDecongestion ); + } + +#ifdef DEBUG + /* probably bogus call, but this is for debug only anyway */ + SocketGetRemoteHost( client, &remotehost, &remoteport ); + TRACE("Decongestion de %s:%hu\n", remotehost, remoteport ); +#endif /*DEBUG */ +} + + + static void *ClientCreate( Client client ) { - // #ifdef DEBUG + char appName[64]; char *remotehost; unsigned short remoteport; + SocketGetRemoteHost( client, &remotehost, &remoteport ); - printf ("%s : Connexion de %s:%hu client=%p\n", - ApplicationName, remotehost, remoteport, client); + snprintf (appName, sizeof (appName), " %s:%hu", remotehost, remoteport); + // #ifdef DEBUG + + TRACE ("%s : Connexion de %s client=%p\n", ApplicationName, appName, client); // #endif /*DEBUG */ - return SendService (client, "Unknown"); + + if (CheckConnected (client)) { + TRACE ("Quitting already connected %s\n", appName); + printf ("ClientCreate Quitting already connected %s\n", appName); + // IvySendError( client, 0, "Application already connected" ); + SocketClose( client ); + return (NULL); + } + + return SendService (client, appName); } + + static void BroadcastReceive( Client client, void *data, char *line ) { Client app; int err; int version; unsigned short serviceport; - char appid[2048]; + char appid[128]; char appname[2048]; unsigned short remoteport; char *remotehost = 0; @@ -680,16 +781,16 @@ static void BroadcastReceive( Client client, void *data, char *line ) remotehost, remoteport); return; } - if ( version != VERSION ) { + if ( version != IVYMAJOR_VERSION ) { /* ignore the message */ SocketGetRemoteHost (client, &remotehost, &remoteport ); fprintf (stderr, "Bad Ivy version, expected %d and got %d from %s:%d\n", - VERSION, version, remotehost, remoteport); + IVYMAJOR_VERSION, version, remotehost, remoteport); return; } /* check if we received our own message. SHOULD ALSO TEST THE HOST */ if ( strcmp( appid , ApplicationID) ==0 ) return; - if (serviceport == ApplicationPort) return; + // if (serviceport == ApplicationPort) return; #ifdef DEBUG SocketGetRemoteHost (client, &remotehost, &remoteport ); @@ -698,11 +799,13 @@ static void BroadcastReceive( Client client, void *data, char *line ) /* connect to the service and send the regexp */ app = SocketConnectAddr(SocketGetRemoteAddr(client), serviceport, 0, Receive, - ClientDelete ); + ClientDelete, ClientDecongestion ); if (app) { IvyClientPtr clnt; clnt = SendService( app, appname ); SocketSetData( app, clnt); + SocketSetUuid (clnt->client, appid); + } else { printf ("SocketConnectAddr error .....\n"); SocketSetData( app, NULL); @@ -724,13 +827,14 @@ static unsigned long currentTime() static const char * GenApplicationUniqueIdentifier() { - static char appid[2048]; + static char appid[128]; unsigned long curtime; curtime = currentTime(); srand( curtime ); - sprintf(appid,"%d:%lu:%d",rand(),curtime,ApplicationPort); + snprintf(appid, sizeof (appid), "%d:%lu:%d", rand(), curtime, ApplicationPort); return appid; } + void IvyInit (const char *appname, const char *ready, IvyApplicationCallback callback, void *data, IvyDieCallback die_callback, void *die_data @@ -784,9 +888,11 @@ void IvyStart (const char* bus) /* * Initialize TCP port */ - server = SocketServer (ANYPORT, ClientCreate, ClientDelete, Receive); + server = SocketServer (ANYPORT, ClientCreate, ClientDelete, + ClientDecongestion, Receive); ApplicationPort = SocketServerGetPort (server); ApplicationID = GenApplicationUniqueIdentifier(); + /* * Find network list as well as broadcast port @@ -806,7 +912,7 @@ void IvyStart (const char* bus) if (q && (port = atoi (q+1))) SupervisionPort = port; else - SupervisionPort = DEFAULT_BUS; + SupervisionPort = IVY_DEFAULT_BUS; /* * Now we have a port number it's time to initialize the UDP port @@ -847,7 +953,7 @@ void IvyStart (const char* bus) if ( IN_MULTICAST( mask ) ) SocketAddMember (broadcast , mask ); - SocketSendBroadcast (broadcast, mask, SupervisionPort, "%d %hu %s %s\n", VERSION, ApplicationPort, ApplicationID, ApplicationName); + SocketSendBroadcast (broadcast, mask, SupervisionPort, "%d %hu %s %s\n", IVYMAJOR_VERSION, ApplicationPort, ApplicationID, ApplicationName); numelem = 0; mask = 0xffffffff; } @@ -888,8 +994,10 @@ IvyUnbindMsg (MsgRcvPtr msg) IvyClientPtr clnt; /* Send to already connected clients */ IVY_LIST_EACH (allClients, clnt ) { - MsgSendTo( clnt->client, DelRegexp,msg->id, ""); + MsgSendTo( clnt, DelRegexp,msg->id, ""); } + free (msg->regexp); + msg->regexp = NULL; IVY_LIST_REMOVE( msg_recv, msg ); } @@ -921,7 +1029,7 @@ IvyBindMsg (MsgCallback callback, void *user_data, const char *fmt_regex, ... ) /* Send to already connected clients */ /* recherche dans la liste des requetes recues de mes clients */ IVY_LIST_EACH( allClients, clnt ) { - MsgSendTo( clnt->client, AddRegexp,msg->id,msg->regexp); + MsgSendTo( clnt, AddRegexp,msg->id,msg->regexp); } return msg; } @@ -942,12 +1050,13 @@ IvyChangeMsg (MsgRcvPtr msg, const char *fmt_regex, ... ) substituteInterval (&buffer); /* change Msg in the query list */ + free (msg->regexp); msg->regexp = strdup(buffer.data); /* Send to already connected clients */ /* recherche dans la liste des requetes recues de mes clients */ IVY_LIST_EACH( allClients, clnt ) { - MsgSendTo( clnt->client, AddRegexp,msg->id,msg->regexp); + MsgSendTo(clnt, AddRegexp,msg->id,msg->regexp); } return msg; } @@ -1077,7 +1186,7 @@ void IvySendError( IvyClientPtr app, int id, const char *fmt, ... ) buffer.offset = 0; make_message( &buffer, fmt, ap ); va_end ( ap ); - MsgSendTo( app->client, Error, id, buffer.data); + MsgSendTo(app, Error, id, buffer.data); } void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data) @@ -1088,12 +1197,12 @@ void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data) void IvySendDirectMsg( IvyClientPtr app, int id, char *msg ) { - MsgSendTo( app->client, DirectMsg, id, msg); + MsgSendTo( app, DirectMsg, id, msg); } void IvySendDieMsg( IvyClientPtr app ) { - MsgSendTo( app->client, Die, 0, "" ); + MsgSendTo(app, Die, 0, "" ); } char *IvyGetApplicationName( IvyClientPtr app ) @@ -1119,11 +1228,22 @@ void IvyDefaultApplicationCallback( IvyClientPtr app, void *user_data, IvyApplic case IvyApplicationDisconnected: printf("Application: %s bye on %s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app)); break; + case IvyApplicationCongestion: + printf("Application: %s congestion on %s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app)); + break; + case IvyApplicationDecongestion: + printf("Application: %s decongestion on %s\n", IvyGetApplicationName( app ), IvyGetApplicationHost(app)); + break; + case IvyApplicationFifoFull: + printf("Application: %s fifo full, msg on %s will be lost until decongestion\n", + IvyGetApplicationName( app ), IvyGetApplicationHost(app)); + break; default: printf("Application: %s unkown event %d\n",IvyGetApplicationName( app ), event); break; } } + void IvyDefaultBindCallback( IvyClientPtr app, void *user_data, int id, char* regexp, IvyBindEvent event) { switch ( event ) { @@ -1257,31 +1377,17 @@ static void freeClient ( IvyClientPtr client) static void delRegexpForOneClientFromDictionary (const char *regexp, const IvyClientPtr client) { MsgSndDictPtr msgSendDict = NULL; - IvyClientPtr client_itr, next; - TRACE ("ENTER delRegexpForOneClientFromDictionary clnt=%d, reg='%s'\n", client, regexp); + // printf ("DBG> ENTER delRegexpForOneClientFromDictionary clnt=%d, reg='%s'\n", client, regexp); + +/* static int called = 0; */ +/* called ++; */ +/* if ((called %1) == 0) { */ +/* printf ("DBG> delRegexpForOneClientFromDictionary called =%d\n", called); */ +/* } */ HASH_FIND_STR(messSndByRegexp, regexp, msgSendDict); if (msgSendDict != NULL) { - /* la clef est trouvée, on itere sur la liste de client associée */ - IVY_LIST_EACH_SAFE ( msgSendDict->clientList, client_itr, next) { - /* pour tester 2 IvyClientPtr, on teste la similarité - des pointeur Client qui doivent être uniques */ - if (client_itr->client == client->client) { - /* on a trouve le client : on l'enleve */ - IVY_LIST_REMOVE (msgSendDict->clientList, client_itr); - TRACE ("delRegexpForOneClientFromDictionary : IVY_LIST_REMOVE\n"); - } - } - /* si la liste de clients associée à cette regexp est vide */ - if ((msgSendDict->clientList == NULL) || (IVY_LIST_IS_EMPTY (msgSendDict->clientList))) { - TRACE ("delRegexpForOneClientFromDictionary : IvyBindingFree, free, hash_del\n"); - /* on efface le binding */ - IvyBindingFree (msgSendDict->binding); - /* on enlève l'entrée regexp de la table de hash */ - HASH_DEL (messSndByRegexp, msgSendDict); - /* on efface la clef (regexp source) */ - free (msgSendDict->regexp_src); - } + delOneIvyClientFromDictionaryEntry (msgSendDict, client); } #ifdef OPENMP regenerateRegPtrArrayCache (); @@ -1290,6 +1396,77 @@ static void delRegexpForOneClientFromDictionary (const char *regexp, const IvyCl +static void delOneIvyClientFromDictionaryEntry (MsgSndDictPtr msgSendDict, + const IvyClientPtr client) +{ + IvyClientPtr client_itr, next; + + + + // printf ("DBG> delRegexpForOneClientFromDictionary, regexp '%s' found\n", regexp); + /* la clef est trouvée, on itere sur la liste de client associée */ + IVY_LIST_EACH_SAFE ( msgSendDict->clientList, client_itr, next) { + /* pour tester 2 IvyClientPtr, on teste la similarité + des pointeur Client qui doivent être uniques */ + if ((client_itr->client == client->client) && (client_itr->id == client->id)) { + /* on a trouve le client : on l'enleve */ + free (client_itr->app_name); + client_itr->app_name = NULL; + TRACE ("delOneClientFromDictionaryEntry : IVY_LIST_REMOVE\n"); + IVY_LIST_REMOVE (msgSendDict->clientList, client_itr); + } + } + /* si la liste de clients associée à cette regexp est vide */ + if ((msgSendDict->clientList == NULL) || + (IVY_LIST_IS_EMPTY (msgSendDict->clientList))) { + TRACE ("delRegexpForOneClientFromDictionary : IvyBindingFree, free, hash_del\n"); + //printf ("DBG> delRegexpForOneClientFromDictionary : IvyBindingFree, free, hash_del\n"); + /* on efface le binding */ + IvyBindingFree (msgSendDict->binding); + /* on enlève l'entrée regexp de la table de hash */ + HASH_DEL (messSndByRegexp, msgSendDict); + /* on efface la clef (regexp source) */ + free (msgSendDict->regexp_src); + /* on libère la structure */ + free (msgSendDict); + } +} + + + +static void delOneClientFromDictionaryEntry (MsgSndDictPtr msgSendDict, + const Client client) +{ + IvyClientPtr client_itr, next; + + /* la clef est trouvée, on itere sur la liste de client associée */ + IVY_LIST_EACH_SAFE ( msgSendDict->clientList, client_itr, next) { + /* pour tester 2 IvyClientPtr, on teste la similarité + des pointeur Client qui doivent être uniques */ + if (client_itr->client == client) { + /* on a trouve le client : on l'enleve */ + free (client_itr->app_name); + client_itr->app_name = NULL; + TRACE ("delOneClientFromDictionaryEntry : IVY_LIST_REMOVE\n"); + IVY_LIST_REMOVE (msgSendDict->clientList, client_itr); + } + } + /* si la liste de clients associée à cette regexp est vide */ + if ((msgSendDict->clientList == NULL) || + (IVY_LIST_IS_EMPTY (msgSendDict->clientList))) { + TRACE ("delRegexpForOneClientFromDictionary : IvyBindingFree, free, hash_del\n"); + /* on efface le binding */ + IvyBindingFree (msgSendDict->binding); + /* on enlève l'entrée regexp de la table de hash */ + HASH_DEL (messSndByRegexp, msgSendDict); + /* on efface la clef (regexp source) */ + free (msgSendDict->regexp_src); + /* on libère la structure */ + free (msgSendDict); + } + +} + static void delAllRegexpsFromDictionary () { @@ -1328,8 +1505,7 @@ static void delAllRegexpsFromDictionary () // HASH_ADD_KEYPTR (hh_name, head, key_ptr, key_len, item_ptr) // HASH_ADD_STR ( head, keyfield_name, item_ptr) -static void addRegexpToDictionary (const char* regexp, IvyClientPtr client, int id, - IvyBinding ivyBind) +static void addRegexpToDictionary (const char* regexp, IvyClientPtr client) { MsgSndDictPtr msgSendDict = NULL; IvyClientPtr newClient = NULL; @@ -1337,9 +1513,18 @@ static void addRegexpToDictionary (const char* regexp, IvyClientPtr client, int HASH_FIND_STR(messSndByRegexp, regexp, msgSendDict); /* l'entree n'existe pas dans le dictionnaire : on la cree */ if (msgSendDict == NULL) { + const char *errbuf; + int erroffset; + msgSendDict = malloc (sizeof (struct _msg_snd_dict)); msgSendDict->regexp_src = strdup (regexp); - msgSendDict->binding = ivyBind; + + msgSendDict->binding = IvyBindingCompile(regexp, & erroffset, & errbuf ); + if (msgSendDict->binding == NULL ) { + printf("Error compiling '%s', %s\n", regexp, errbuf); + MsgSendTo(client, Error, erroffset, errbuf ); + } + msgSendDict->clientList = NULL; /* HASH_ADD_STR ne fonctionne que si la clef est un tavbleau de char, si c'est un pointeur @@ -1361,7 +1546,7 @@ static void addRegexpToDictionary (const char* regexp, IvyClientPtr client, int newClient->app_name = strdup (client->app_name); newClient->app_port = client->app_port; newClient->client = client->client; - newClient->id = id; + newClient->id = client->id; /* au niveau du champ liste de client du dictionnaire, on n'a pas besoin de la liste des regexps sources (qui n'est necessaire que pour la liste globale des clients) */ @@ -1371,12 +1556,11 @@ static void addRegexpToDictionary (const char* regexp, IvyClientPtr client, int -static void changeRegexpInDictionary (const char* regexp, IvyClientPtr client, - int id, IvyBinding ivyBind) +static void changeRegexpInDictionary (const char* regexp, IvyClientPtr client) { // printf ("ENTER changeRegexpInDictionary\n"); delRegexpForOneClientFromDictionary (regexp, client); - addRegexpToDictionary (regexp, client, id, ivyBind); + addRegexpToDictionary (regexp, client); } @@ -1385,52 +1569,69 @@ static void changeRegexpInDictionary (const char* regexp, IvyClientPtr client, /* met a jour le dictionnaire et la liste globale */ static void delOneClient (const Client client) { - IvyClientPtr client_itr; - GlobRegPtr regxpSrc =NULL, next; + IvyClientPtr client_itr, next; + MsgSndDictPtr msgSendDict, mnext=NULL; - TRACE ("ENTER delOneClient\n"); /* on cherche le client dans la liste globale des clients */ - IVY_LIST_ITER (allClients, client_itr, client_itr->client != client ); - /* si on le trouve */ - if (client_itr != NULL) { - TRACE ("DEBUG delOneClient %s, client_itr->client=%p, clientRef=%p\n", - client_itr->app_name, client_itr->client, client); - - - - - /* pour chaque regexp source de ce client */ - IVY_LIST_EACH_SAFE (client_itr->srcRegList, regxpSrc, next) { - /* on met a jour la liste des clients associee a la regexp source */ - delRegexpForOneClient (regxpSrc->str_regexp, client_itr, regxpSrc->id); - /* on libere la memoire associee a la regexp source */ - if (regxpSrc->str_regexp != NULL) { - free (regxpSrc->str_regexp); - regxpSrc->str_regexp = NULL; + IVY_LIST_EACH_SAFE(allClients, client_itr, next) { + GlobRegPtr regxpSrc =NULL, next; + /* si on le trouve */ + if (client_itr->client == client) { + + /* pour chaque regexp source de ce client */ + IVY_LIST_EACH_SAFE (client_itr->srcRegList, regxpSrc, next) { + /* on met a jour la liste des clients associee a la regexp source */ + delRegexpForOneClient (client_itr, regxpSrc->id); + /* on libere la memoire associee a la regexp source */ + /* probablement deja fait ailleurs d'après valgrind */ + /* if (regxpSrc->str_regexp != NULL) { */ + /* free (regxpSrc->str_regexp); */ + /* regxpSrc->str_regexp = NULL; */ + /* } */ } + + + /* on libere la liste de regexp source */ + IVY_LIST_EMPTY (client_itr->srcRegList); + /* on enleve l'entree correspondant a ce client dans la liste globale */ + IVY_LIST_REMOVE (allClients, client_itr); + } + } + + /* on cherche dans le dictionnaire des regexps, les regexps qui ont + ce client dans leur liste de client associés et on vire les entrées*/ - /* on libere la liste de regexp source */ - IVY_LIST_EMPTY (client_itr->srcRegList); - /* on enleve l'entree correspondant a ce client dans la liste globale */ - IVY_LIST_REMOVE (allClients, client_itr); + + // forme un peu compliquée pour faire un parcours de liste "securisé" car + // on libère la mémoire de l'element courrant dans le corp de la boucle + // ce qui oblige a recuperer le champ next avant de faire ce free + for ( msgSendDict = messSndByRegexp ; + (mnext = msgSendDict ? msgSendDict->hh.next: msgSendDict ),msgSendDict ; + msgSendDict = mnext ) { + delOneClientFromDictionaryEntry (msgSendDict, client); } + +#ifdef OPENMP + regenerateRegPtrArrayCache (); +#endif } -static char delRegexpForOneClient (const char *regexp, const IvyClientPtr client, int id) +static char delRegexpForOneClient (const IvyClientPtr client, int id) { IvyClientPtr client_itr = NULL; GlobRegPtr regxpSrc = NULL, next = NULL; char removed = 0; + + TRACE ("ENTER delRegexpForOneClient id=%d\n", id); + // printf ("DBG> ENTER delRegexpForOneClient id=%d\n", id); /* on enleve du dictionnaire */ - delRegexpForOneClientFromDictionary (regexp, client); - /* on enleve de la liste globale */ /* recherche du client */ IVY_LIST_ITER (allClients, client_itr, client_itr->client != client->client ); @@ -1441,6 +1642,7 @@ static char delRegexpForOneClient (const char *regexp, const IvyClientPtr client if (regxpSrc->id == id) { removed = 1; if (regxpSrc->str_regexp != NULL) { + delRegexpForOneClientFromDictionary (regxpSrc->str_regexp, client); free (regxpSrc->str_regexp); regxpSrc->str_regexp = NULL; } @@ -1452,8 +1654,7 @@ static char delRegexpForOneClient (const char *regexp, const IvyClientPtr client return (removed); } -static void addOrChangeRegexp (const char* regexp, IvyClientPtr client, int id, - IvyBinding ivyBind) +static void addOrChangeRegexp (const char* regexp, IvyClientPtr client) { MsgSndDictPtr msgSendDict = NULL; IvyClientPtr client_itr = NULL; @@ -1463,23 +1664,22 @@ static void addOrChangeRegexp (const char* regexp, IvyClientPtr client, int id, HASH_FIND_STR(messSndByRegexp, regexp, msgSendDict); /* la regexp n'existe pas du tout */ if (msgSendDict == NULL) { - addRegexp (regexp, client, id, ivyBind); + addRegexp (regexp, client); } else { /* la regexp existe, mais l'id existe elle pour le client */ IVY_LIST_ITER( msgSendDict->clientList, client_itr, ( client_itr->client != client->client)); - if (( client_itr != NULL) && (client_itr->id == id)) { + if (( client_itr != NULL) && (client_itr->id == client->id)) { /* si oui on fait un change regexp */ - changeRegexp (regexp, client, id, ivyBind); + changeRegexp (regexp, client); } else { /* si non on fait un add regexp */ - addRegexp (regexp, client, id, ivyBind); + addRegexp (regexp, client); } } } -static void addRegexp (const char* regexp, IvyClientPtr client, int id, - IvyBinding ivyBind) +static void addRegexp (const char* regexp, IvyClientPtr client) { IvyClientPtr client_itr = NULL; GlobRegPtr regxpSrc = NULL; @@ -1488,7 +1688,7 @@ static void addRegexp (const char* regexp, IvyClientPtr client, int id, // printf ("ENTER addRegexp\n"); /* on ajoute au dictionnaire */ - addRegexpToDictionary (regexp, client, id, ivyBind); + addRegexpToDictionary (regexp, client); /* on ajoute a la liste globale */ /* recherche du client */ @@ -1507,24 +1707,23 @@ static void addRegexp (const char* regexp, IvyClientPtr client, int id, /* on ajoute la regexp à la liste de regexps */ IVY_LIST_ADD_START (client_itr->srcRegList, regxpSrc); - regxpSrc->id = id; + regxpSrc->id = client->id; regxpSrc->str_regexp = strdup (regexp); IVY_LIST_ADD_END (client_itr->srcRegList, regxpSrc); if (application_bind_callback) { - (*application_bind_callback)( client, application_bind_data, id, regexp, IvyAddBind); + (*application_bind_callback)( client, application_bind_data, client->id, regexp, IvyAddBind); } } -static void changeRegexp (const char* regexp, IvyClientPtr client, int id, - IvyBinding ivyBind) +static void changeRegexp (const char* regexp, IvyClientPtr client) { IvyClientPtr client_itr = NULL; GlobRegPtr regxpSrc = NULL, next = NULL; /* on change dans le dictionnaire */ - // printf ("ENTER changeRegexp\n"); - changeRegexpInDictionary (regexp, client, id , ivyBind); + // printf ("ENTER changeRegexp\n"); + changeRegexpInDictionary (regexp, client); /* on change dans la liste globale */ /* recherche du client */ @@ -1533,14 +1732,14 @@ static void changeRegexp (const char* regexp, IvyClientPtr client, int id, /* pour chaque regexp source de ce client */ IVY_LIST_EACH_SAFE (client_itr->srcRegList, regxpSrc, next) { /* si on trouve notre regexp, on la change */ - if (regxpSrc->id == id) { + if (regxpSrc->id == client->id) { free (regxpSrc->str_regexp); regxpSrc->str_regexp = strdup (regexp); } } } if (application_bind_callback) { - (*application_bind_callback)( client, application_bind_data, id, regexp, IvyChangeBind); + (*application_bind_callback)( client, application_bind_data, client->id, regexp, IvyChangeBind); } } -- cgit v1.1