Initial revision
authorteodor <teodor>
Wed, 22 Sep 2004 16:23:41 +0000 (16:23 +0000)
committerteodor <teodor>
Wed, 22 Sep 2004 16:23:41 +0000 (16:23 +0000)
Makefile [new file with mode: 0644]
rtop.c [new file with mode: 0644]
sendtop.c [new file with mode: 0644]
td_lmsg.c [new file with mode: 0644]
td_smsg.c [new file with mode: 0644]
td_unit.c [new file with mode: 0644]
top.h [new file with mode: 0644]
topd.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e531efd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,32 @@
+CC=gcc
+AR=ar rcv
+RANLIB=ranlib
+LD=ld -x -shared
+
+INCLUDE=-I. -I../tedtools
+CFLAGS=-Wall -g -O2 -pedantic -ansi -DASSERT_CORE -D_GNU_SOURCE -DHAVE_POLL_H -DHAVE_SYS_POLL_H -DHAVE_HSTRERROR
+LIB=-L../tedtools -ltedtools
+
+PROGS=sendtop topd rtop
+
+.SUFFIXES: .o.c
+
+all: $(PROGS)
+
+rtop: rtop.o
+       $(CC) -o $@ $< $(LIB)
+
+sendtop: sendtop.o
+       $(CC) -o $@ $< $(LIB)
+
+topd: topd.o td_unit.o td_smsg.o td_lmsg.o
+       $(CC) -o $@ topd.o td_unit.o td_smsg.o td_lmsg.o $(LIB)
+
+.c.o:
+       $(CC) $(CFLAGS) $(INCLUDE) -c $<
+
+
+clean:
+       rm -rf $(PROGS) *.o
+       rm -rf *core *gmon* nohup.out
+
diff --git a/rtop.c b/rtop.c
new file mode 100644 (file)
index 0000000..c204aaf
--- /dev/null
+++ b/rtop.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "tlog.h"
+#include "connection.h"
+#include "tmalloc.h"
+#include "top.h"
+
+int
+main( int argc, char *argv[] ) {
+       int ch;
+       int debug=0;
+       char *host="127.0.0.1";
+       int port=TOPD_SERVER_DEFAULT_PORT;
+       int i;
+
+       MassiveUnit *mu;
+       TCMsg   *pmsg = (TCMsg*)malloc( TCMSGHDRSZ );
+       TC_Connection  cs;
+
+       pmsg->type = TOPGETTYPE;
+       pmsg->len = TCMSGHDRSZ;
+
+       while( (ch=getopt(argc, argv, "Dh:p:"))!=-1) {
+               switch(ch) {
+                       case 'D':
+                               debug=1;
+                               break;
+                       case 'h':
+                               host=strdup(optarg);
+                               break;
+                       case 'p':
+                               port=atoi(optarg);
+                               break;
+                       default:
+                               return 1;
+               }
+       }
+
+        if ( debug )
+                opentlog( TL_OPEN_STDERR,  TL_DEBUG, NULL);
+        else
+                opentlog( TL_OPEN_SYSLOG, TL_INFO, NULL);
+
+       TC_fillConnection(&cs, host, port);
+       cs.buf = (char*)pmsg;
+       cs.len = pmsg->len;
+       if ( TC_Talk(&cs) == CS_OK ) {  
+               pmsg = (TCMsg*) cs.buf;
+               mu = (MassiveUnit*)pmsg->data;
+
+               printf("\tIP\tLoad\tFree\tTotal\tData\n");
+               for(i=0; i<mu->number; i++) 
+                       printf("%s\t%.2f\t%.1fM\t%.1fM\t%s",
+                               inet_ntoa(mu->units[i].ip),
+                               mu->units[i].top.load,
+                               ((float) mu->units[i].top.freemem)/( 1024*1024.0 ),
+                               ((float) mu->units[i].top.usermem)/( 1024*1024.0 ),
+                               ctime( &(mu->units[i].stamp) )
+                       );
+       }
+       
+       TC_FreeConnection(&cs);
+                               
+       return 0;
+}
+
diff --git a/sendtop.c b/sendtop.c
new file mode 100644 (file)
index 0000000..8ab3269
--- /dev/null
+++ b/sendtop.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *     may be used to endorse or promote products derived from this software
+ *     without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/sysctl.h>
+
+#include "tlog.h"
+#include "tmalloc.h"
+#include "connection.h"
+
+#include "top.h"
+
+#define NITEM   0
+
+static int
+getsysctl(char *name, void *ptr, size_t len) {
+       size_t nlen = len;
+       if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
+               tlog(TL_ALARM, "sysctl(%s...) failed: %s\n", name,
+                       strerror(errno));
+               return 1;
+       }   
+       if (nlen != len) {
+               tlog(TL_ALARM, "sysctl(%s...) expected %lu, got %lu\n", name,
+                       (unsigned long)len, (unsigned long)nlen);
+               return 1;
+       }
+       return 0;
+}
+
+
+#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
+
+static void
+fillMsgTop(TCMsgTop *m) {
+       double lll[3];
+       int    memory_tmp;
+
+       memset(m,0,sizeof(TCMsgTop));
+       if ( getloadavg(lll,3) >= NITEM+1 )
+               m->load=lll[NITEM];
+       else
+               m->load=-1.0;
+
+       m->freemem = 0;
+       if ( GETSYSCTL("vm.stats.vm.v_inactive_count", memory_tmp) == 0 )
+               m->freemem += memory_tmp;
+       else
+               m->freemem = -1;
+       if ( m->freemem>=0 && GETSYSCTL("vm.stats.vm.v_cache_count", memory_tmp) == 0 )
+               m->freemem += memory_tmp;
+       else
+               m->freemem = -1;
+       if ( m->freemem>=0 && GETSYSCTL("vm.stats.vm.v_free_count", memory_tmp) == 0 )
+               m->freemem += memory_tmp;
+       else
+               m->freemem = -1;
+
+       if (  m->freemem>=0 )
+               m->freemem *= getpagesize();
+        
+       m->usermem =-1;
+       if ( GETSYSCTL("hw.usermem", memory_tmp) == 0 )
+               m->usermem = memory_tmp;
+
+       tlog( TL_DEBUG, "Sended topdata: %.2f load, %d free, %d total", m->load, m->freemem, m->usermem);
+}
+
+static int
+sendTop(Msg *msg) {
+       TCMsg *pmsg;
+
+       if ( !msg->msg ) {
+               int msglen = TCMSGHDRSZ + sizeof(TCMsgTop);
+               pmsg = (TCMsg*)tmalloc(msglen);
+               pmsg->len = msglen;
+               pmsg->type=TOPMSGTYPE;
+               msg->msg = pmsg;
+       } else {
+               pmsg = msg->msg;
+       }
+
+       fillMsgTop( (TCMsgTop*)(pmsg->data) );
+
+       return TC_sendMsg(msg);
+}
+
+
+extern char *optarg;
+int
+main( int argc, char *argv[] ) {
+       int ch;
+       Msg     msg;
+       int debug=0, child=0;
+       int period=30;
+
+       msg.port        = TOPD_SERVER_DEFAULT_PORT;
+       msg.host        = "127.0.0.1";
+       msg.msg = NULL;
+       msg.sockfd =-1;
+
+       while( (ch=getopt(argc, argv, "h:p:s:D"))!=-1) {
+               switch(ch) {
+                       case 'h':
+                               msg.host = strdup(optarg);
+                               break;
+                       case 'p':
+                               msg.port = atoi(optarg);
+                               break;
+                       case 's':
+                               period = atoi(optarg);
+                               break;
+                       case 'D':
+                               debug=1;
+                               break;
+                       default:
+                               return 1;
+               }
+       }
+
+       signal(SIGCHLD, SIG_IGN);
+
+       if ( debug )
+               opentlog( TL_OPEN_STDERR,  TL_DEBUG, NULL);
+       else
+               opentlog( TL_OPEN_SYSLOG, TL_INFO, NULL);
+
+       if ( debug || (child = fork()) == 0 ) {
+               while(1) {
+                       sendTop(&msg);
+                       sleep(period);  
+               }
+               TC_closefd(&msg);       
+       }
+       
+       if (child == -1)
+               tlog(TL_CRIT|TL_EXIT, "Can't start child process: %s", strerror(errno));
+
+       return (0);
+}
diff --git a/td_lmsg.c b/td_lmsg.c
new file mode 100644 (file)
index 0000000..7f27280
--- /dev/null
+++ b/td_lmsg.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "tlog.h"
+#include "connection.h"
+#include "top.h"   
+#include "tmalloc.h"
+
+static void 
+getTopData(TC_Connection *conn) {
+       TCMsg *pmsg;
+       conn->len = TCMSGHDRSZ + MUHDRSZ + cfg.mu->number * sizeof(UnitInfo);
+       conn->buf = trealloc( conn->buf, conn->len );
+       pmsg = (TCMsg*) conn->buf;
+       
+       pmsg->len = conn->len;
+       pmsg->type = TOPGETTYPE;
+       memcpy( pmsg->data, cfg.mu, pmsg->len - TCMSGHDRSZ );
+       ((MassiveUnit*)pmsg->data)->maxnumber = cfg.mu->number;
+       TC_Send(conn);   
+}
+       
+static void 
+gotLongMessage( TC_Connection *conn ) {
+       TCMsg *pmsg = (TCMsg*) conn->buf;
+
+       if ( conn->ptr - conn->buf < TCMSGHDRSZ ) {
+               tlog(TL_ALARM,"Wrong size of long message (%d bytes)", conn->ptr - conn->buf);
+               conn->state = CS_ERROR;
+               return;
+       }
+       
+       switch(pmsg->type) {
+               case TOPGETTYPE:
+                       getTopData(conn);
+                       break;
+               default:
+                       tlog(TL_ALARM,"Got unknown packet type: %d", pmsg->type);
+                       conn->state = CS_ERROR;
+       }
+}
+
+static void
+sendedLongMessage( TC_Connection *conn ) {
+       TCMsg *pmsg = (TCMsg*) conn->buf;
+       switch(pmsg->type) {
+               case TOPGETTYPE:
+                       conn->state = CS_FINISH;
+                       break;
+               default:
+                       tlog(TL_ALARM,"Send unknown packet type: %d", pmsg->type);
+                       conn->state = CS_ERROR;
+       }
+}
+
+void
+ConnectionWorks() {
+       int i;
+       TC_Connection *conn;
+       for(i=TC_SERVER_CONN_START; i<cfg.pool.number; i++) {
+               conn = cfg.pool.conn[i];
+               switch( conn->state ) {
+                       case CS_INPROCESS:
+                               TC_ServerConnect( conn );
+                               break;
+                       case CS_CONNECTED: /* we have connected to remote host */
+                               TC_Send( conn );
+                               break;
+                       case CS_FINISHSEND:
+                               sendedLongMessage( conn );
+                               break;
+                       case CS_FINISHREAD:
+                               gotLongMessage( conn );
+                               break;
+                       case CS_READ:
+                               if ( conn->readyio ) {
+                                       TC_Read( conn );
+                                       if ( conn->state != CS_READ ) i--; /* check it one more time */ 
+                               }
+                               break;
+                       case CS_SEND:
+                               if ( conn->readyio ) {
+                                       TC_Send( conn );
+                                       if ( conn->state != CS_SEND ) i--; /* check it one more time */ 
+                               }
+                               break;
+                       /* ignore */
+                       case CS_OK: 
+                       case CS_AGAIN:
+                       case CS_WAIT: /* ??? */
+                               break;
+                       /* out */
+                       case CS_TIMEOUT:
+                       case CS_CLOSED:
+                       case CS_NOTINITED:
+                       case CS_FINISH:
+                       case CS_ERROR:
+                       default:
+                               tlog(TL_DEBUG, "Clear N%d connection", i);
+                               TC_deleteConnectionByN(&cfg.pool,i);
+                               i--;
+               }
+       }
+}
diff --git a/td_smsg.c b/td_smsg.c
new file mode 100644 (file)
index 0000000..3bfded6
--- /dev/null
+++ b/td_smsg.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+
+#include "tlog.h"
+#include "connection.h"
+#include "top.h"
+#include "tmalloc.h"
+
+
+static void
+addMsgTop( MassiveUnit *mu, TCMsgTop *tmsg, struct in_addr *client ) {
+        UnitInfo unit;
+
+        memcpy( &(unit.top), tmsg, sizeof( TCMsgTop ));
+        unit.stamp=time(NULL);
+        memcpy( &(unit.ip), client, sizeof(struct in_addr) );
+        unit.flag = 0;
+
+        fillUnit(mu, &unit);
+}
+
+
+void
+gotMsg(TC_Connection *msgconn) {
+       Msg gmsg;
+       TCMsg *pmsg;
+
+       if ( TC_getMsg( msgconn->fd, &gmsg ) )
+                       return;
+
+       pmsg = gmsg.msg;
+       
+       if ( cfg.debug )
+               tlog(TL_DEBUG, "Got %d bytes %08x type from %s:%d",
+                       pmsg->len,
+                       pmsg->type,
+                       inet_ntoa(gmsg.host_addr.sin_addr),
+                       ntohs(gmsg.host_addr.sin_port)
+               );
+
+       switch( pmsg->type ) {
+               case TOPMSGTYPE:
+                       addMsgTop( cfg.mu, (TCMsgTop*)(pmsg->data), &(gmsg.host_addr.sin_addr) );
+                       break;
+               default:
+                       tlog(TL_ALARM, "Unknown message type: %d from %s",
+                               pmsg->type, inet_ntoa(gmsg.host_addr.sin_addr));
+       }
+}
diff --git a/td_unit.c b/td_unit.c
new file mode 100644 (file)
index 0000000..c736284
--- /dev/null
+++ b/td_unit.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "tlog.h"
+#include "connection.h"
+#include "top.h"
+#include "tmalloc.h"
+
+
+MassiveUnit*
+allocUnits(int n ) {
+       MassiveUnit *ptr = NULL;
+
+       ptr = (MassiveUnit*)malloc( MUHDRSZ + n * sizeof(UnitInfo) );
+       if ( !ptr ) 
+               tlog(TL_CRIT|TL_EXIT, "allocUnits: no memoru for %d units", n);
+       ptr->maxnumber = n;
+       ptr->number=0;
+
+       return ptr;
+}
+
+static int
+cmpUnit(const void *a, const void *b) {
+       if ( ((UnitInfo*)a)->ip.s_addr == ((UnitInfo*)b)->ip.s_addr )
+               return 0;
+       return ( ((UnitInfo*)a)->ip.s_addr > ((UnitInfo*)b)->ip.s_addr ) ? 1 : -1;
+}
+
+void
+fillUnit( MassiveUnit* mu, UnitInfo *unit ) {
+       if ( mu->number==0 || ( mu->number==1 && unit->ip.s_addr == mu->units->ip.s_addr ) ) {
+               memcpy( mu->units, unit, sizeof(UnitInfo) );
+               mu->number=1;
+       } else {
+               UnitInfo *ptr = bsearch(unit, mu->units, mu->number, sizeof(UnitInfo), cmpUnit);
+               if ( ptr ) 
+                       memcpy( ptr, unit, sizeof(UnitInfo) );
+               else {
+                       if ( mu->number == mu->maxnumber )
+                               tlog(TL_ALARM, "Can't add new unit");
+                       else {
+                               ptr = mu->units + mu->number;
+                               memcpy( ptr, unit, sizeof(UnitInfo) );
+                               mu->number++;
+                               qsort(mu->units, mu->number, sizeof(UnitInfo), cmpUnit);
+                       } 
+               }
+       }
+}
+
+
diff --git a/top.h b/top.h
new file mode 100644 (file)
index 0000000..ca89a59
--- /dev/null
+++ b/top.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *        notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *        notice, this list of conditions and the following disclaimer in the
+ *        documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *        may be used to endorse or promote products derived from this software
+ *        without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TOP_H__
+#define __TOP_H__
+
+#include <sys/types.h>
+#include "connection.h"
+
+#define TOPD_SERVER_DEFAULT_PORT       6543
+#define TOPMSGTYPE                     0x10AD10AD
+#define TOPGETTYPE                     0x06ED10AD
+
+typedef struct {
+        double  load;
+        int     freemem;
+        int     usermem;
+} TCMsgTop;
+
+typedef struct {
+        TCMsgTop        top;
+        time_t          stamp;
+        struct in_addr  ip;
+        u_int32_t       flag;
+} UnitInfo;
+
+typedef struct {
+        u_int32_t  maxnumber;
+        u_int32_t  number;
+        UnitInfo   units[1];
+} MassiveUnit;
+
+#define MUHDRSZ         (2*sizeof(u_int32_t))
+
+MassiveUnit *allocUnits(int n);
+void fillUnit( MassiveUnit* mu, UnitInfo *unit );
+
+void gotMsg(TC_Connection *msgconn);
+void ConnectionWorks();
+
+typedef struct {
+        MassiveUnit *mu;
+        u_int32_t
+                        debug:1,
+                        unused:31;
+        PoolConnection  pool;
+} TCServer;
+
+extern TCServer cfg;
+
+#define TC_SERVER_CONN_START    2
+
+#endif
diff --git a/topd.c b/topd.c
new file mode 100644 (file)
index 0000000..56a7e03
--- /dev/null
+++ b/topd.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/sysctl.h>
+
+#include "tlog.h"
+#include "connection.h"
+#include "top.h"
+#include "tmalloc.h"
+
+TCServer cfg;
+static int continueWork=1;
+
+static void
+inquireExit(int s) {
+        continueWork=0;
+}
+                                
+extern char *optarg;
+extern int optind;
+
+int
+main( int argc, char *argv[] ) {
+       int ch;
+       int child=0, listenport = TOPD_SERVER_DEFAULT_PORT;
+        int n=1024;
+       char *host="127.0.0.1";
+
+       memset( &cfg, 0, sizeof(TCServer) );
+
+       while( (ch=getopt(argc, argv, "h:p:c:s:D"))!=-1) {
+               switch(ch) {
+                        case 'D':
+                                cfg.debug=1;
+                                break;
+                        case 'h':
+                                host=strdup(optarg);
+                                break;
+                        case 'p':
+                                listenport=atoi(optarg);
+                                break;
+                        case 'n':
+                                n=atoi(optarg);
+                                break;
+                       default:
+                               return 1;
+               }
+       }
+
+       signal(SIGCHLD, SIG_IGN);
+
+        if ( cfg.debug )
+                opentlog( TL_OPEN_STDERR,  TL_DEBUG, NULL);
+        else
+                opentlog( TL_OPEN_SYSLOG, TL_INFO, NULL);
+
+       if ( cfg.debug || (child = fork()) == 0 ) {
+               /* child */
+               if ( cfg.debug || (child = fork()) == 0 ) {
+                       /*child*/
+                       TC_Connection *newconn;
+                       int i;
+
+                       signal(SIGINT, inquireExit);
+                       signal(SIGHUP, inquireExit);
+
+                       if ( n <= 0 )
+                               n=1024;
+
+                       cfg.mu = allocUnits(n);
+
+                       TC_addConnection( &cfg.pool, TC_fillConnection(NULL, NULL, listenport) );
+                       TC_ClientInitConnection( cfg.pool.conn[0], NULL, listenport);
+                       cfg.pool.conn[0]->state = CS_READ;
+
+                       TC_addConnection( &cfg.pool, TC_fillConnection(NULL, NULL, listenport) );
+                       cfg.pool.conn[1]->fd = TC_AcceptUdp( host, listenport );
+                       cfg.pool.conn[1]->state = CS_READ; 
+
+                       while(continueWork) {
+                               if ( TC_ReadyIO(cfg.pool.conn, cfg.pool.number, 100 ) ) {
+                                       if ( cfg.pool.conn[1]->readyio ) 
+                                               gotMsg( cfg.pool.conn[1] );
+                                       else 
+                                               tlog(TL_DEBUG,"Ready connection...");
+                               }
+                               ConnectionWorks();
+                               if ( cfg.pool.conn[0]->readyio && (newconn=TC_AcceptTcp( cfg.pool.conn[0] )) != NULL ) {
+                                       if ( newconn->state == CS_CONNECTED ) {
+                                               tlog(TL_DEBUG,"Accept new connection...");
+                                               newconn->state = CS_READ;
+                                               TC_addConnection( &cfg.pool, newconn );
+                                       }
+                               }
+                       }
+                       TC_deleteConnectionByN(&cfg.pool, 0);
+                       close( cfg.pool.conn[1]->fd );
+                       for(i=TC_SERVER_CONN_START; i<cfg.pool.number; i++) 
+                               TC_deleteConnectionByN(&cfg.pool,i);
+               }
+       }
+       if (child == -1) 
+               tlog(TL_CRIT,"Can't start child process");
+
+       return 0;
+}
+