summaryrefslogtreecommitdiff
path: root/src/ivy.c
diff options
context:
space:
mode:
authorbustico2008-03-21 09:03:34 +0000
committerbustico2008-03-21 09:03:34 +0000
commit6ca781b8a38474ab428d5fcb3b489dfe3e974334 (patch)
tree8c8725c88c3fd031d632a9f2b1f7376d1cb3c75b /src/ivy.c
parent50236114f04a0050625bedee7c4c02b36b1213ae (diff)
downloadivy-c-6ca781b8a38474ab428d5fcb3b489dfe3e974334.zip
ivy-c-6ca781b8a38474ab428d5fcb3b489dfe3e974334.tar.gz
ivy-c-6ca781b8a38474ab428d5fcb3b489dfe3e974334.tar.bz2
ivy-c-6ca781b8a38474ab428d5fcb3b489dfe3e974334.tar.xz
- numerous fixes
- socket in non blocking mode (resolve some deadlock, and agent are immune to another agent beeing blocked)
Diffstat (limited to 'src/ivy.c')
-rw-r--r--src/ivy.c571
1 files changed, 385 insertions, 186 deletions
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 <stdarg.h>
#include <ctype.h>
-
-
#include <fcntl.h>
+
+#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);
}
}