Mysterious delay.
Hi,
I have a database/socket program that tends to sit & wait too much. Most of the time, if I send one line over the socket connection, it will handle it, and read 2 lines out of the database. Once in a while, it will process around 50 lines in the database. But then it goes back to 2 lines. I don't understand why it is waiting for receiving something on the socket. I have the program set to start at msg# 8000. There are over 9000 messages. There is no reason it shouldn't be able to process them all without waiting. I am including the main code. If you want to see the entire code in the check out yungblood.com / gateway.tgz
If you need to know anything about the code, please let me know. I believe this issue is the last major problem in getting my code running.
Hi,
I have a database/socket program that tends to sit & wait too much. Most of the time, if I send one line over the socket connection, it will handle it, and read 2 lines out of the database. Once in a while, it will process around 50 lines in the database. But then it goes back to 2 lines. I don't understand why it is waiting for receiving something on the socket. I have the program set to start at msg# 8000. There are over 9000 messages. There is no reason it shouldn't be able to process them all without waiting. I am including the main code. If you want to see the entire code in the check out yungblood.com / gateway.tgz
If you need to know anything about the code, please let me know. I believe this issue is the last major problem in getting my code running.
Code:
int sendline(struct client *client, const char *format, ...) {
int rv=1;
int len;
va_list arg;
char buf[4096];
va_start(arg, format);
rv=vsprintf(buf, format, arg);
va_end(arg);
// logmsg("<<< Sent: %s", buf);
len=strlen(buf);
while (client->outcur+len>=client->outsize) {
client->outbuf=xrealloc(client->outbuf, client->outsize*2);
client->outsize*=2;
}
memcpy(client->outbuf+client->outcur,buf,len+1);
client->outcur+=len;
}
Code:
int main(int argc, char** argv) {
int i,j,res, sql;
int acfd;
struct sockaddr_in acsa;
char readbuf[1000],relaystring[1000];
struct in_addr targetaddr;
MYSQL_ROW row;
long int msgid=8000;
char user[32], msg[2048], dest[32];
if(logmsg("Starting gateway daemon.")<0) {
fprintf(stderr, "Failed to start logging. Exiting.\n");
return 0;
}
/* Connect to database */
if((mysql_init(&mysql))==NULL) {
logmsg("Failed to initate MySQL connection. Exiting.");
return 0;
}
if(!mysql_real_connect(&mysql, MYSQL_HOST, MYSQL_USERNAME, MYSQL_PASSWD, MYSQL_DATABASE, 0, NULL, 0)) {
logmsg("Failed to connect to MySQL: Error: %s. Exiting.", mysql_error(&mysql));
return 0;
}
close(0);
close(1);
signal(SIGPIPE,SIG_IGN);
strcpy(relaystring,FAILMESSAGE);
if (-1==(acfd=socket(PF_INET,SOCK_STREAM,0))) {
logmsg("socket(accept_socket)");
exit(1);
}
acsa.sin_family=AF_INET;
acsa.sin_port=htons(SERV_PORT);
acsa.sin_addr.s_addr=INADDR_ANY;
#ifdef SO_REUSEADDR
{
int reuseit=1;
if (-1==setsockopt(acfd,SOL_SOCKET,SO_REUSEADDR,(char*)&reuseit,sizeof(reuseit))) logmsg("setsockopt SOL_SOCKET SO_REUSEADDR");
}
#endif
if (-1==bind(acfd,(struct sockaddr*)&acsa,sizeof(struct sockaddr_in))) {
logmsg("bind");
exit(1);
}
/* 5 is usual the maximum anyway */
if (-1==listen(acfd,5)) {
logmsg("listen");
exit(1);
}
while (1) {
fd_set readfds,writefds;
int width;
width=3;
if (acfd>=width) width=acfd+1;
restart_select:
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(acfd,&readfds);
sql=0;
sprintf(readbuf, "SELECT * from chat where msgid > '%d' order by time limit 1", msgid);
if (mysql_query(&mysql, readbuf) == 0) {
if (result = mysql_store_result(&mysql)) {
if (mysql_num_rows(result)) {
row = mysql_fetch_row(result);
msgid=atol(row[0]);
strcpy(user, row[1]);
strcpy(msg, row[2]);
strcpy(dest, row[4]);
sp2nb(user);
sp2nb(dest);
logmsg("SQL >> %ld %s %s %s\r\n", msgid, user, msg, dest);
sql = 1;
}
mysql_free_result(result);
}
}
for (i=numofclients;i--;) {
struct client *client = clients+i;
/* Do we have a message in the database waiting? */
if (sql) {
if (strcmp(user, "System") == 0) {
sendline(client, ":%s!%s@%s PRIVMSG %s :%s\r\n", user, user, USER_DOMAIN, CHAN_NAME, msg);
}
else if (dest[0] == 0)
sendline(client, ":%s!%s@%s PRIVMSG %s :%s\r\n", user, user, USER_DOMAIN, CHAN_NAME, msg);
else if (strcmp(dest, client->nick) == 0)
sendline(client, ":%s!%s@%s PRIVMSG %s :%s\r\n", user, user, USER_DOMAIN, client->nick, msg);
}
/* Clean up excess allocated memory */
while ((client->insize>DEFAULTSIZE) && (client->incur<client->insize/2)) {
client->inbuf=xrealloc(client->inbuf,client->insize/2);
client->insize/=2;
}
while ((client->outsize>DEFAULTSIZE) && (client->outcur<client->outsize/2)) {
client->outbuf=xrealloc(client->outbuf,client->outsize/2);
client->outsize/=2;
}
/* Closed? -> clean */
if (client->flags & FLAG_CLOSED) {
clean_connection(client);
continue;
}
/* Quit & transmitted all stuff left to user? -> clean */
if ((client->flags&FLAG_QUIT)&&(!client->outcur)) {
clean_connection(client);
continue;
}
if (client->sockfd>=0) {
/*need to do that... else it will cause load 1*/
if (client->outcur) FD_SET(client->sockfd,&writefds);
if (!(client->flags & FLAG_EOF)) FD_SET(client->sockfd,&readfds);
if (client->sockfd>=width) width=client->sockfd+1;
}
}
if (-1==select(width, (FD_CAST*)&readfds, (FD_CAST*)&writefds, NULL,/*no exceptfds.*/ 0)) {
if (errno!=EINTR) logmsg("select");
else goto restart_select;
}
if (FD_ISSET(acfd,&readfds)) {
int afd;
int aclen;
struct sockaddr_in conaddr;
struct client *client = NULL;
aclen=sizeof(struct sockaddr_in);
if (-1==(afd=accept(acfd,(struct sockaddr*)&conaddr,&aclen))) logmsg("accept");
if (clients) clients=(struct client*)xrealloc(clients,sizeof(struct client)*(numofclients+1));
else clients=(struct client*)xmalloc(sizeof(struct client));
numofclients++;
if (numofclients > maxclients) maxclients = numofclients;
client = clients+(numofclients-1);
client->inbuf = xmalloc(DEFAULTSIZE);
client->outbuf = xmalloc(DEFAULTSIZE);
client->insize = DEFAULTSIZE;
client->outsize = DEFAULTSIZE;
client->flags = 0;
client->incur = 0;
client->outcur = 0;
client->login = 0;
client->sockfd = afd;
client->state = STATE_ACCEPTED;
memcpy(&client->addr,&conaddr,sizeof(struct sockaddr_in));
if (numofclients>=MAXUSERS) {
strcpy(client->outbuf,relaystring);
client->outcur = strlen(relaystring)+1;
client->state = STATE_OK;
client->flags = FLAG_QUIT;
}
#ifdef SO_LINGER
{
struct linger sol;
sol.l_linger = 5;
sol.l_onoff = 1;
if (-1==setsockopt(acfd,SOL_SOCKET,SO_LINGER,(char*)&sol,sizeof(sol))) logmsg("setsockopt SOL_SOCKET SO_LINGER");
}
#endif
}
for (i=numofclients;i--;) {
struct client *client = clients+i;
if ((client->sockfd>=0) && FD_ISSET(client->sockfd,&readfds)) {
do {
if (-1==(res=read(client->sockfd,readbuf,1000))) {
if (errno==EINTR) break;
/* user side has broken the connection */
close(client->sockfd);
client->sockfd=-1;
client->flags |= FLAG_CLOSED;
break;
}
break;
} while (1);
if (res==0) {
/* we read the End Of File marker. but we still have to write the rest of the text */
client->flags |= FLAG_EOF;
}
if (res>0) {
readbuf[res]='\0';
while (client->incur+res>=client->insize) {
client->inbuf=xrealloc(client->inbuf,client->insize*2);
client->insize*=2;
}
memcpy(client->inbuf+client->incur,readbuf,res+1);
client->incur+=res;
}
}
/* Do we have any lines in the buffer? Process them. */
while (gotline(client)) getircmsg(client);
if ((client->sockfd>=0) && FD_ISSET(client->sockfd,&writefds)) {
j=client->outcur;
if (-1==(res=write(client->sockfd,client->outbuf,j))) {
if (errno!=EINTR) {
close(client->sockfd);
client->sockfd=-1;
client->flags |= FLAG_CLOSED;
}
}
if (res>0) {
memcpy(client->outbuf,client->outbuf+res,client->outcur-res);
client->outcur-=res;
}
}
}
}
}
Last edited: