/* * Process all events that have expired relative to the current clock time * (which is not re-evaluated unless clock_NewTime has been called). * The relative time to the next event is returned in the output parameter * next and the function returns 1. If there are is no next event, * the function returns 0. */ int rxevent_RaiseEvents(struct clock * next) { struct rxevent *qe; struct clock now; #ifdef RXDEBUG if (Log) fprintf(Log, "rxevent_RaiseEvents(%ld.%ld)\n", now.sec, now.usec); #endif /* * Events are sorted by time, so only scan until an event is found that * has not yet timed out */ while (queue_IsNotEmpty(&rxevent_queue)) { clock_GetTime(&now); qe = queue_First(&rxevent_queue, rxevent); if (clock_Lt(&now, &qe->eventTime)) { *next = qe->eventTime; clock_Sub(next, &now); return 1; } queue_Remove(qe); rxevent_nPosted--; qe->func(qe, qe->arg, qe->arg1); queue_Append(&rxevent_free, qe); rxevent_nFree++; } return 0; }
/* Refresh value of clock_now. */ void clock_UpdateTime(void) { struct timeval tv; struct clock t; gettimeofday(&tv, 0); t.sec = tv.tv_sec; t.usec = tv.tv_usec; clock_Sub(&t, &tdiff); /* We can't have time running backwards!!! */ if (clock_Le(&t, &clock_now)) { /* Calculate new tdiff. */ t.sec = tv.tv_sec; t.usec = tv.tv_usec; clock_Sub(&t, &clock_now); tdiff.sec = t.sec; tdiff.usec = t.usec; /* Fake new time. */ t.sec = tv.tv_sec; t.usec = tv.tv_usec; clock_Sub(&t, &tdiff); t.usec++; if (t.usec >= 1000000) { t.sec += 1; t.usec = 0; } } clock_now = t; clock_haveCurrentTime = 1; clock_nUpdates++; }
void rxi_calltrace(unsigned int event, struct rx_call *call) { struct clock now; struct rx_trace rxtinfo; if (!rxi_tracename[0]) return; if (rxi_logfd < 0) { rxi_logfd = open(rxi_tracename, O_WRONLY | O_CREAT | O_TRUNC, 0777); if (rxi_logfd < 0) rxi_tracename[0] = '\0'; } clock_GetTime(&now); rxtinfo.event = event; rxtinfo.now = now.sec * 1000 + now.usec / 1000; rxtinfo.cid = call->conn->cid; rxtinfo.call = *(call->callNumber); rxtinfo.qlen = rx_atomic_read(&rx_nWaiting); rxtinfo.servicetime = 0; rxtinfo.waittime = 0; switch (event) { case RX_CALL_END: clock_Sub(&now, &(call->traceStart)); rxtinfo.servicetime = now.sec * 10000 + now.usec / 100; if (call->traceWait.sec) { now = call->traceStart; clock_Sub(&now, &(call->traceWait)); rxtinfo.waittime = now.sec * 10000 + now.usec / 100; } else rxtinfo.waittime = 0; call->traceWait.sec = call->traceWait.usec = call->traceStart.sec = call->traceStart.usec = 0; break; case RX_CALL_START: call->traceStart = now; if (call->traceWait.sec) { clock_Sub(&now, &(call->traceWait)); rxtinfo.waittime = now.sec * 10000 + now.usec / 100; } else rxtinfo.waittime = 0; break; case RX_TRACE_DROP: if (call->traceWait.sec) { clock_Sub(&now, &(call->traceWait)); rxtinfo.waittime = now.sec * 10000 + now.usec / 100; } else rxtinfo.waittime = 0; break; case RX_CALL_ARRIVAL: call->traceWait = now; default: break; } memcpy(rxi_tracebuf + rxi_tracepos, &rxtinfo, sizeof(struct rx_trace)); rxi_tracepos += sizeof(struct rx_trace); if (rxi_tracepos >= (4096 - sizeof(struct rx_trace))) rxi_flushtrace(); }
int main(int argc, char **argv) { char *hostname; struct hostent *hostent; afs_uint32 host; int logstdout = 0; struct rx_connection *conn; struct rx_call *call; struct rx_peer *peer; int err = 0; int nCalls = 1, nBytes = 1; int bufferSize = 4000000; char *buffer; char *sendFile = 0; int setFD = 0; int jumbo = 0; #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) setlinebuf(stdout); rxi_syscallp = test_syscall; #endif argv++; argc--; while (argc && **argv == '-') { if (strcmp(*argv, "-silent") == 0) print = 0; if (strcmp(*argv, "-jumbo") == 0) jumbo = 1; else if (strcmp(*argv, "-nc") == 0) nCalls = atoi(*++argv), argc--; else if (strcmp(*argv, "-nb") == 0) nBytes = atoi(*++argv), argc--; else if (strcmp(*argv, "-np") == 0) rx_nPackets = atoi(*++argv), argc--; else if (!strcmp(*argv, "-nsf")) rxi_nSendFrags = atoi(*++argv), argc--; else if (!strcmp(*argv, "-nrf")) rxi_nRecvFrags = atoi(*++argv), argc--; else if (strcmp(*argv, "-twind") == 0) rx_initSendWindow = atoi(*++argv), argc--; else if (strcmp(*argv, "-rwind") == 0) rx_initReceiveWindow = atoi(*++argv), argc--; else if (strcmp(*argv, "-rxlog") == 0) rxlog = 1; else if (strcmp(*argv, "-logstdout") == 0) logstdout = 1; else if (strcmp(*argv, "-eventlog") == 0) eventlog = 1; else if (strcmp(*argv, "-drop") == 0) { #ifdef RXDEBUG rx_intentionallyDroppedPacketsPer100 = atoi(*++argv), argc--; #else fprintf(stderr, "ERROR: Compiled without RXDEBUG\n"); #endif } else if (strcmp(*argv, "-burst") == 0) { burst = atoi(*++argv), argc--; burstTime.sec = atoi(*++argv), argc--; burstTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-retry") == 0) { retryTime.sec = atoi(*++argv), argc--; retryTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-timeout") == 0) timeout = atoi(*++argv), argc--; else if (strcmp(*argv, "-fill") == 0) fillPackets++; else if (strcmp(*argv, "-file") == 0) sendFile = *++argv, argc--; else if (strcmp(*argv, "-timereadvs") == 0) timeReadvs = 1; else if (strcmp(*argv, "-wait") == 0) { /* Wait time between calls--to test lastack code */ waitTime.sec = atoi(*++argv), argc--; waitTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-compute") == 0) { /* Simulated "compute" time for each call--to test acknowledgement protocol. This is simulated by doing an iomgr_select: imperfect, admittedly. */ computeTime.sec = atoi(*++argv), argc--; computeTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-fd") == 0) { /* Open at least this many fd's. */ setFD = atoi(*++argv), argc--; } else { err = 1; break; } argv++, argc--; } if (err || argc != 1) Quit("usage: rx_ctest [-silent] [-rxlog] [-eventlog] [-nc NCALLS] [-np NPACKETS] hostname"); hostname = *argv++, argc--; if (rxlog || eventlog) { if (logstdout) debugFile = stdout; else debugFile = fopen("rx_ctest.db", "w"); if (debugFile == NULL) Quit("Couldn't open rx_ctest.db"); if (rxlog) rx_debugFile = debugFile; if (eventlog) rxevent_debugFile = debugFile; } signal(SIGINT, intSignal); /*Changed to sigquit since dbx is broken right now */ #ifndef AFS_NT40_ENV signal(SIGQUIT, quitSignal); #endif #ifdef AFS_NT40_ENV if (afs_winsockInit() < 0) { printf("Can't initialize winsock.\n"); exit(1); } rx_EnableHotThread(); #endif rx_SetUdpBufSize(256 * 1024); if (!jumbo) rx_SetNoJumbo(); hostent = gethostbyname(hostname); if (!hostent) Abort("host %s not found", hostname); if (hostent->h_length != 4) Abort("host address is disagreeable length (%d)", hostent->h_length); memcpy((char *)&host, hostent->h_addr, sizeof(host)); if (setFD > 0) OpenFD(setFD); if (rx_Init(0) != 0) { printf("RX failed to initialize, exiting.\n"); exit(2); } if (setFD > 0) { printf("rx_socket=%d\n", rx_socket); } printf("Using %d packet buffers\n", rx_nPackets); conn = rx_NewConnection(host, htons(2500), 3, rxnull_NewClientSecurityObject(), 0); if (!conn) Abort("unable to make a new connection"); /* Set initial parameters. This is (currently) not the approved interface */ peer = rx_PeerOf(conn); if (burst) peer->burstSize = peer->burst = burst; if (!clock_IsZero(&burstTime)) peer->burstWait = burstTime; if (!clock_IsZero(&retryTime)) peer->rtt = _8THMSEC(&retryTime); if (sendFile) SendFile(sendFile, conn); else { buffer = (char *)osi_Alloc(bufferSize); while (nCalls--) { struct clock startTime; struct timeval t; int nbytes; int nSent; int bytesSent = 0; int bytesRead = 0; call = rx_NewCall(conn); if (!call) Abort("unable to make a new call"); clock_GetTime(&startTime); for (bytesSent = 0; bytesSent < nBytes; bytesSent += nSent) { int tryCount; tryCount = (bufferSize > nBytes - bytesSent) ? nBytes - bytesSent : bufferSize; nSent = rx_Write(call, buffer, tryCount); if (nSent == 0) break; } for (bytesRead = 0; (nbytes = rx_Read(call, buffer, bufferSize)); bytesRead += nbytes) { }; if (print) printf("Received %d characters in response\n", bytesRead); err = rx_EndCall(call, 0); if (err) printf("Error %d returned from rpc call\n", err); else { struct clock totalTime; float elapsedTime; clock_GetTime(&totalTime); clock_Sub(&totalTime, &startTime); elapsedTime = clock_Float(&totalTime); fprintf(stderr, "Sent %d bytes in %0.3f seconds: %0.0f bytes per second\n", bytesSent, elapsedTime, bytesSent / elapsedTime); } if (!clock_IsZero(&computeTime)) { t.tv_sec = computeTime.sec; t.tv_usec = computeTime.usec; if (select(0, 0, 0, 0, &t) != 0) Quit("Select didn't return 0"); } if (!clock_IsZero(&waitTime)) { struct timeval t; t.tv_sec = waitTime.sec; t.tv_usec = waitTime.usec; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &t); #else IOMGR_Sleep(t.tv_sec); #endif } if (debugFile) rx_PrintPeerStats(debugFile, rx_PeerOf(conn)); rx_PrintPeerStats(stdout, rx_PeerOf(conn)); } } Quit("testclient: done!\n"); return 0; }
int SendFile(char *file, struct rx_connection *conn) { struct rx_call *call; int fd; struct stat status; int blockSize, bytesLeft; char *buf; int nbytes; int err; struct clock startTime; int receivedStore = 0; struct clock totalReadvDelay; int nReadvs; int code; #ifdef AFS_AIX_ENV #include <sys/statfs.h> struct statfs tstatfs; #endif if (timeReadvs) { nReadvs = 0; clock_Zero(&totalReadvDelay); } fd = open(file, O_RDONLY, 0); if (fd < 0) Abort("Couldn't open %s\n", file); fstat(fd, &status); #ifdef AFS_NT40_ENV blockSize = 1024; #else #ifdef AFS_AIX_ENV /* Unfortunately in AIX valuable fields such as st_blksize are gone from the stat structure!! */ fstatfs(fd, &tstatfs); blockSize = tstatfs.f_bsize; #else blockSize = status.st_blksize; #endif #endif buf = (char *)osi_Alloc(blockSize); bytesLeft = status.st_size; clock_GetTime(&startTime); call = rx_NewCall(conn); while (bytesLeft) { if (!receivedStore && rx_GetRemoteStatus(call) == 79) { receivedStore = 1; fprintf(stderr, "Remote status indicates file accepted (\"received store\")\n"); } nbytes = (bytesLeft > blockSize ? blockSize : bytesLeft); errno = 0; code = read(fd, buf, nbytes); if (code != nbytes) { Abort("Only read %d bytes of %d, errno=%d\n", code, nbytes, errno); } code = rx_Write(call, buf, nbytes); if (code != nbytes) { Abort("Only wrote %d bytes of %d\n", code, nbytes); } bytesLeft -= nbytes; } while ((nbytes = rx_Read(call, buf, sizeof(buf))) > 0) { char *p = buf; while (nbytes--) { putchar(*p); p++; } } if ((err = rx_EndCall(call, 0)) != 0) { fprintf(stderr, "rx_Endcall returned error %d\n", err); } else { struct clock totalTime; float elapsedTime; clock_GetTime(&totalTime); clock_Sub(&totalTime, &startTime); elapsedTime = totalTime.sec + totalTime.usec / 1e6; fprintf(stderr, "Sent %d bytes in %0.3f seconds: %0.0f bytes per second\n", (int) status.st_size, elapsedTime, status.st_size / elapsedTime); if (timeReadvs) { float delay = clock_Float(&totalReadvDelay) / nReadvs; fprintf(stderr, "%d readvs, average delay of %0.4f seconds\n", nReadvs, delay); } } close(fd); return(0); }