long async_send(SendQEntry *entry) /* Entry points to info about a message ... determine which transport mechanism is appropriate and send as much as possible without blocking. Right now just shared memory ... when sockets are working this routine will become async_shmem_send. Shared-memory protocol aims for low latency. Each process has one buffer for every other process. Thus, to send a message U merely have to determine if the receivers buffer for you is empty and copy directly into the receivers buffer. Return 0 data has not been sent, 1 if the send is complete. */ { long node = entry->node; ShmemBuf *sendbuf= TCGMSG_proc_info[node].sendbuf; #ifdef NOTIFY_SENDER void *busy_flag = &TCGMSG_proc_info[node].recvbuf->flag; #endif long ncopy, complete; long pval; long info[4]; pair_t pair; #ifdef DEBUG2 (void) fprintf(stdout,"%2ld: sending to %ld buf=%lx len=%ld\n", TCGMSG_nodeid, node, entry->buf, entry->lenbuf); (void) fprintf(stdout,"%2ld: sendbuf=%lx\n", TCGMSG_nodeid, sendbuf); (void) fflush(stdout); #endif /* return if the receiver buffer is not available */ #ifdef NOTIFY_SENDER if ((pval = local_flag(busy_flag))) { #else if ((pval = remote_flag(&sendbuf->info[3], node))) { #endif # ifdef DEBUG { long info[4]; FLUSH_CACHE; COPY_FROM_REMOTE(sendbuf->info, info, sizeof(info), node); fprintf(stdout,"%2ld: snd info after full = %ld %ld %ld\n", TCGMSG_nodeid, info[0], info[1], info[2]); fflush(stdout); sleep(1); } # endif return 0; } /* if data has been written already and we are here, operation is complete */ if(entry->written) return 1L; # ifdef NOTIFY_SENDER set_local_flag(busy_flag,true); # endif info[0] = entry->type; info[1] = entry->lenbuf; info[2] = entry->tag; #if 0 entry->buffer_number++; info[3] = entry->buffer_number; #else pair.n.from = TCGMSG_nodeid; pair.n.to = node; info[3] = pair.fromto; #endif /* Copy over the message if it fits in the receiver buffer */ ncopy = (long) (( entry->lenbuf <= SHMEM_BUF_SIZE) ? entry->lenbuf : 0 ); GET_LOC_BUF(localbuf); if (ncopy) { # ifdef DEBUG printf("%ld:snd:copying data node=%ld adr=%lx %ld bytes\n",TCGMSG_nodeid, node, sendbuf->buf, ncopy); fflush(stdout); # endif COPY_TO_LOCAL(entry->buf+entry->written, localbuf->buf, ncopy); complete = 1; } else { # ifdef DEBUG printf("%ld:snd:copying addr node=%ld adr=%lx %ld bytes\n",TCGMSG_nodeid, node, sendbuf->buf, ncopy); fflush(stdout); # endif /* copy address of the user buffer to the send buffer */ COPY_TO_LOCAL(&(entry->buf), localbuf->buf, sizeof(char*)); ncopy = sizeof(char*); complete = 0; /* sent is complete only when receiver gets the data */ entry->written = 1; } # ifdef DEBUG printf("%ld:snd:copying info to node=%ld adr=%lx %ld bytes\n",TCGMSG_nodeid, node, sendbuf->info, sizeof(info)); fflush(stdout); # endif COPY_TO_LOCAL(info, localbuf->info, sizeof(info)); COPY_TO_REMOTE_CNTR(localbuf,sendbuf,sizeof(info)+ncopy,node,&sendbuf->cntr); /* advance to next buf */ NEXT_LOC_BUF(localbuf); return complete; } void msg_rcv(long type, char *buf, long lenbuf, long *lenmes, long node) /* Receive a message of given type from the specified node, returning the message and length of the message. Right now just shared memory ... when sockets are working this routine will become msg_shmem_rcv Shared-memory protocol aims for low latency. Each process has one buffer for every other process. Thus, to send a message U merely have to determine if the receivers buffer for you is empty and copy directly into the receivers buffer. */ { long me = TCGMSG_nodeid; ShmemBuf *recvbuf; /* Points to receving buffer */ long nleft; long msg_type, msg_tag, msg_len; long buffer_number = 1; long expected_tag = TCGMSG_proc_info[node].tag_rcv++; #ifdef NOTIFY_SENDER void *busy_flag= &TCGMSG_proc_info[node].sendbuf->flag; #endif if (node<0 || node>=TCGMSG_nnodes) Error("msg_rcv: node is out of range", node); recvbuf = TCGMSG_proc_info[node].recvbuf; /* Wait for first part message to be written */ #ifdef DEBUG (void) fprintf(stdout,"%2ld: receiving from %ld buf=%lx len=%ld\n", me, node, recvbuf,lenbuf); (void) fprintf(stdout,"%2ld: user buf=%lx len=%ld\n", me, buf, lenbuf); (void) fflush(stdout); #endif #ifdef LAPI lapi_await(&recvbuf->info[3], buffer_number, &recvbuf->cntr); #else local_await(&recvbuf->info[3], buffer_number); #endif /* Copy over the header information */ msg_type = recvbuf->info[0]; msg_len = recvbuf->info[1]; msg_tag = recvbuf->info[2]; #ifdef DEBUG (void) fprintf(stdout,"%2ld: received msg from %ld len=%ld\n", me, node, msg_len); (void) fflush(stdout); #endif /* Check type and size information */ if(msg_tag != expected_tag) { pair_t pair; pair.fromto = recvbuf->info[3]; fprintf(stdout, "rcv: me=%ld from=%ld type=%ld expectedtag=%ld lenbuf=%ld\ngot: to=%d from=%d type=%ld msg_tag=%ld msg_len=%ld info[3]=%ld\n", me, node, type, expected_tag, lenbuf, (int)pair.n.to, (int)pair.n.from, msg_type, msg_tag, msg_len, recvbuf->info[3]); fflush(stdout); Error("msg_rcv: tag mismatch ... transport layer failed????", 0L); } if (msg_type != type) { (void) fprintf(stderr, "rcv: me=%ld from=%ld type=(%ld != %ld) tag=%ld len=%ld\n", me, node, type, msg_type, msg_tag, msg_len); Error("msg_rcv: type mismatch ... strong typing enforced\n", 0L); } if (msg_len > lenbuf) { (void) fprintf(stderr, "rcv: me=%ld from=%ld type=%ld tag=%ld len=(%ld > %ld)\n", me, node, type, msg_tag, msg_len, lenbuf); Error("msg_rcv: message too long for buffer\n", 0L); } nleft = *lenmes = msg_len; if (nleft) { long ncopy = nleft; /* for short messages data is in local buffer, for long in remote buffer */ if(nleft <= SHMEM_BUF_SIZE) { # if defined(CRAY_T3D) && !defined(CRAY_T3E) /* cache flushing optimizations for T3D */ long line; if(ncopy < 321) for(line = 0; line < ncopy; line+=32) FLUSH_CACHE_LINE(recvbuf->buf+line); else # endif FLUSH_CACHE; COPY_FROM_LOCAL(recvbuf->buf, buf, ncopy); }else { char *addr = *((char**)recvbuf->buf); # ifdef CRAY_T3D /* WILL NOT WORK ON T3D for data not alligned on 8-byte boundary !!! */ if(nleft&7)Error("msg_rcv: not alligned",nleft); # endif COPY_FROM_REMOTE(addr, buf, nleft, node); } } recvbuf->info[3] = false; #ifdef NOTIFY_SENDER /* confirm that data has been transfered */ set_remote_flag(busy_flag,false,node); #endif }
inline int add_logfile_entry(time_t date, struct in_addr src_ip, unsigned long src_port, struct in_addr dst_ip, unsigned long dst_port, double packets, double bytes, struct t_ip_groups *groups ) { char date_str[80]; int src_grp, dst_grp; int traf_idx; int flag_local1, flag_local2; /* Если начальное время еще неопределено, берем его из перой строки */ if (groups->start == (time_t)-1) { struct tm t; /* Округляем время на начало часа */ localtime_r(&date, &t); t.tm_sec = 0; t.tm_min = 0; groups->start = mktime(&t); if ( groups->start == (time_t)-1 ) { fprintf(stderr, "cannot convert time\n"); return -1; } } traf_idx = time2idx(groups->start, date); if ( traf_idx < 0 || traf_idx >= MAX_HOUR_CNT) { ctime_r(&groups->start, date_str); date_str[24]='\0'; fprintf(stderr, "timedate out of range +Start time: %s, max num hour: %u\n", date_str, MAX_HOUR_CNT); return -2; } /* Максимальный индекс для опеределения с какого и по какое время выдавать результат */ if ( groups->traf_max < traf_idx) groups->traf_max = traf_idx; src_grp = lookup_ip(groups, src_ip, &flag_local1); dst_grp = lookup_ip(groups, dst_ip, &flag_local2); if ( (src_grp == -1) && (dst_grp >= 0) ) { /* Входящий трафик (к клиенту) */ groups->grp[dst_grp].traf_inb[traf_idx] += bytes; }else if ( (src_grp >= 0) && (dst_grp == -1) ) { /* Исходящий трафик (от клиента) */ groups->grp[src_grp].traf_outb[traf_idx] += bytes; }else if ( (src_grp >= 0) && (dst_grp >= 0) ) { /* * Локальный трафик (либо между узлами определенными в группах) * Его надо либо не считать, либо записывать только в одну группу * Если его записывать в обе группы, он испортит общую статистику * по загрузке. */ /* groups->grp[dst_grp].traf_inb[traf_idx] += bytes; */ /* Выводим трафик как локальный. local_flag устанавливается чтобы * выводить меньше одинаковых строк локального трафика */ if ( !flag_local1 || !flag_local2 ) { char src_ip_str[16]; char dst_ip_str[16]; set_local_flag(groups, src_ip, 1); set_local_flag(groups, dst_ip, 1); strncpy(src_ip_str, inet_ntoa(src_ip), sizeof(src_ip_str) - 1); strncpy(dst_ip_str, inet_ntoa(dst_ip), sizeof(dst_ip_str) - 1); ctime_r(&date, date_str); date_str[24]='\0'; fprintf(stderr, "local: %s(%i) from %s:%lu(%i) to %s:%lu(%i) - %lg packets %lg bytes\n", date_str, traf_idx, src_ip_str, src_port, src_grp>=0?groups->grp[src_grp].num:src_grp, dst_ip_str, dst_port, dst_grp>=0?groups->grp[dst_grp].num:dst_grp, packets, bytes); } }else /*if ( (src_grp == -1 ) && (dst_grp == -1) ) */ { /* Неопределенный трафик */ char src_ip_str[16]; char dst_ip_str[16]; strncpy(src_ip_str, inet_ntoa(src_ip), sizeof(src_ip_str) - 1); strncpy(dst_ip_str, inet_ntoa(dst_ip), sizeof(dst_ip_str) - 1); ctime_r(&date, date_str); date_str[24]='\0'; fprintf(stderr, "unknown: %s(%i) from %s:%lu(%i) to %s:%lu(%i) - %lg packets %lg bytes\n", date_str, traf_idx, src_ip_str, src_port, src_grp>=0?groups->grp[src_grp].num:src_grp, dst_ip_str, dst_port, dst_grp>=0?groups->grp[dst_grp].num:dst_grp, packets, bytes); } return 0; }