/* background daemon for timing out transactions */ static void* BKGLoop(void *unused) { struct timeval tv; int loop = 0; afs_pthread_setname_self("vol bkg"); while (1) { tv.tv_sec = GCWAKEUP; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV #ifdef AFS_NT40_ENV Sleep(GCWAKEUP * 1000); #else select(0, 0, 0, 0, &tv); #endif #else (void)IOMGR_Select(0, 0, 0, 0, &tv); #endif GCTrans(); TryUnlock(); loop++; if (loop == 10) { /* reopen log every 5 minutes */ loop = 0; ReOpenLog(); } } AFS_UNREACHED(return(NULL)); }
// ping_fs is a callback routine meant to be called from within // cm_SearchCellFile() or cm_SearchCellDNS() static long pingFS(void *ping_params, struct sockaddr_in *addrp, char *namep) { int rc; struct ping_params * pp = (struct ping_params *) ping_params; if ( pp->max_hosts && pp->hosts_attempted >= pp->max_hosts ) return 0; pp->hosts_attempted++; if (pp->port && addrp->sin_port != htons(pp->port)) addrp->sin_port = htons(pp->port); rc = fsprobe_Init(1, addrp, pp->retry_delay, fsHandler, pp->verbose); if (rc) { fprintf(stderr, "fsprobe_Init failed (%d)\n", rc); fsprobe_Cleanup(1); return 0; } for (;;) { tv.tv_sec = pp->host.wait; tv.tv_usec = 0; if (IOMGR_Select(0, 0, 0, 0, &tv)) break; } probeComplete(); return(0); }
static void ares_worker_thread(char *ptr) { struct timeval tv, max_tv = { 30, 0 }; fd_set readset, writeset; int nfds, ret; while (1) { FD_ZERO(&readset); FD_ZERO(&writeset); nfds = ares_fds(achannel, &readset, &writeset); if (nfds == 0) { tv = max_tv; IOMGR_Sleep(max_tv.tv_sec); } else { struct timeval *tvp; tvp = ares_timeout(achannel, &max_tv, &tv); ret = IOMGR_Select(nfds, &readset, &writeset, NULL, tvp); if (ret < 0) /* XXX some error, lets ignore that for now */; else if (ret == 0) /* timeout */; else ares_process(achannel, &readset, &writeset); } } }
int SSAMPLE_Inc(struct rx_call *call) { afs_int32 code, temp; struct ubik_trans *tt; struct timeval tv; code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt); if (code) return code; printf("about to set lock\n"); /* now set database locks. Must do this or people may read uncommitted * data. Note that we're just setting a lock at position 1, which is * this program's convention for locking the whole database */ code = ubik_SetLock(tt, 1, 1, LOCKWRITE); printf("now have lock\n"); if (code) { ubik_AbortTrans(tt); return code; } /* sleep for a little while to make it possible for us to test for some * race conditions */ if (sleepTime) { tv.tv_sec = sleepTime; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif } /* read the original value */ code = ubik_Read(tt, &temp, sizeof(afs_int32)); if (code == UEOF) { /* short read */ temp = 0; } else if (code) { ubik_AbortTrans(tt); return code; } temp++; /* bump the value here */ /* reset the file pointer back to where it was before the read */ code = ubik_Seek(tt, 0, 0); if (code) { ubik_AbortTrans(tt); return code; } /* write the data back */ code = ubik_Write(tt, &temp, sizeof(afs_int32)); if (code) { ubik_AbortTrans(tt); return code; } /* finally, we commit the transaction */ code = ubik_EndTrans(tt); temp = 0; return code; }
static void onStrike(void *foo) { while (1) { printf("[onstrike] I'll never quit, block, block, block\n"); IOMGR_Select(0, NULL, NULL, NULL, NULL); printf("[onstrike] Bah, you will never pay enough\n"); } }
/* LWP_WaitForKeystroke(Unix) :Wait until a key has been struck or time (secconds) * runs out and return to caller. The Unix version will actually wait until * a <cr> has been entered before returning. * Input: * seconds: wait for <seconds> seconds before returning. If seconds < 0, * wait infinitely. * Return Value: * 1: Keyboard input available * 0: seconds elapsed. Timeout. */ int LWP_WaitForKeystroke(int seconds) { fd_set rdfds; int code; struct timeval twait; struct timeval *tp = NULL; #if defined(HAVE_STDIO_EXT_H) if (__fbufsize(stdin) > 0) return 1; #elif defined(AFS_LINUX20_ENV) if (stdin->_IO_read_ptr < stdin->_IO_read_end) return 1; #elif (defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)) && defined(AFS_DFBSD_ENV) struct appx_sbuf { unsigned char *_base; int _size; }; struct APPX_FILE { struct __FILE_public pub; struct appx_sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ }; struct APPX_FILE *appx_stdin = (struct APPX_FILE *) stdin; if (appx_stdin->_bf._size > 0) return 1; #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) if (stdin->_bf._size > 0) return 1; #else if (stdin->_cnt > 0) return 1; #endif FD_ZERO(&rdfds); FD_SET(fileno(stdin), &rdfds); if (seconds >= 0) { twait.tv_sec = seconds; twait.tv_usec = 0; tp = &twait; } #ifdef AFS_PTHREAD_ENV code = select(1 + fileno(stdin), &rdfds, NULL, NULL, tp); #else code = IOMGR_Select(1 + fileno(stdin), &rdfds, NULL, NULL, tp); #endif return (code == 1) ? 1 : 0; }
static void PrintDots() { static struct timeval constSleepTime = { 1, 0 }; struct timeval sleepTime; while (waitingForAnswer) { sleepTime = constSleepTime; IOMGR_Select(0, 0, 0, 0, &sleepTime); if (!waitingForAnswer) break; printf("."); fflush(stdout); } }
static void RanDelay(int t) /* milliseconds */ { uint32_t tx; struct timeval tval; if (t > 0) { tx = (uint32_t)random() % t; tval.tv_sec = tx / 1000; tval.tv_usec = 1000*(tx % 1000); if (VerboseFlag) fprintf(stderr, "delaying for %ld:%ld seconds ....\n", tval.tv_sec, tval.tv_usec); FLUSH(); assert(IOMGR_Select(0, NULL, NULL, NULL, &tval) == 0); } }
afs_int32 canWrite(int fid) { afs_int32 in, out, except; struct timeval tp; afs_int32 code; tp.tv_sec = 0; tp.tv_usec = 0; out = (1 << fid); in = 0; except = 0; code = IOMGR_Select(32, &in, &out, &except, &tp); return (code); }
int SSAMPLE_Test(struct rx_call *call) { afs_int32 code, temp; struct ubik_trans *tt; struct timeval tv; /* first start a new transaction. Must be a write transaction since * we're going to change some data (with ubik_Write) */ code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt); if (code) return code; printf("about to set lock\n"); /* now set database locks. Must do this or people may read uncommitted * data. Note that we're just setting a lock at position 1, which is * this program's convention for locking the whole database */ code = ubik_SetLock(tt, 1, 1, LOCKWRITE); printf("now have lock\n"); if (code) { ubik_AbortTrans(tt); return code; } /* sleep for a little while to make it possible for us to test for some * race conditions */ if (sleepTime) { tv.tv_sec = sleepTime; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif } /* read the original value */ code = ubik_Read(tt, &temp, sizeof(afs_int32)); if (code == UEOF) { printf("short read, using 0\n"); temp = 0; } else if (code) { ubik_AbortTrans(tt); return code; } ubik_AbortTrans(tt); /* surprise! pretend something went wrong */ return code; }
int SSAMPLE_Get(struct rx_call *call, afs_int32 *gnumber) { afs_int32 code, temp; struct ubik_trans *tt; struct timeval tv; /* start with a read transaction, since we're only going to do read * operations in this transaction. */ code = ubik_BeginTrans(dbase, UBIK_READTRANS, &tt); if (code) return code; printf("about to set lock\n"); /* obtain a read lock, so we don't read data the other guy is writing */ code = ubik_SetLock(tt, 1, 1, LOCKREAD); printf("now have lock\n"); if (code) { ubik_AbortTrans(tt); return code; } /* sleep to allow races */ if (sleepTime) { tv.tv_sec = sleepTime; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif } /* read the value */ code = ubik_Read(tt, &temp, sizeof(afs_int32)); if (code == UEOF) { /* premature eof, use 0 */ temp = 0; } else if (code) { ubik_AbortTrans(tt); return code; } *gnumber = temp; /* end the transaction, automatically releasing locks */ code = ubik_EndTrans(tt); return code; }
/* LWP_WaitForKeystroke : Wait until a key has been struck or time (secconds) * runs out and return to caller. The NT version of this function will return * immediately after a key has been pressed (doesn't wait for cr). * Input: * seconds: wait for <seconds> seconds before returning. If seconds < 0, * wait infinitely. * Return Value: * 1: Keyboard input available * 0: seconds elapsed. Timeout. */ int LWP_WaitForKeystroke(int seconds) { time_t startTime, nowTime; double timeleft = 1; #ifndef AFS_PTHREAD_ENV struct timeval twait; twait.tv_sec = 0; twait.tv_usec = LWP_KEYSTROKE_DELAY; #endif time(&startTime); if (seconds >= 0) timeleft = seconds; do { /* check if we have a keystroke */ if (_kbhit()) return 1; if (timeleft == 0) break; /* sleep for LWP_KEYSTROKE_DELAY ms and let other * process run some*/ #ifdef AFS_PTHREAD_ENV Sleep(LWP_KEYSTROKE_DELAY); #else IOMGR_Select(0, 0, 0, 0, &twait); #endif if (seconds > 0) { /* we only worry about elapsed time if * not looping forever (seconds < 0) */ /* now check elapsed time */ time(&nowTime); timeleft = seconds - difftime(nowTime, startTime); } } while (timeleft > 0); return 0; }
/* background daemon for timing out transactions */ static void* BKGLoop(void *unused) { struct timeval tv; time_t now; afs_int32 sleepseconds; int loop = 0; while (1) { now = FT_ApproxTime(); sleepseconds = GCWAKEUP - (now % GCWAKEUP); /* synchronize with wall clock */ tv.tv_sec = sleepseconds; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV #ifdef AFS_NT40_ENV Sleep(GCWAKEUP * 1000); #else select(0, 0, 0, 0, &tv); #endif #else (void)IOMGR_Select(0, 0, 0, 0, &tv); #endif TransferRate(); GCTrans(); TryUnlock(); loop++; if (loop == 10) { /* reopen log every 5 minutes */ loop = 0; ReOpenLog(AFSDIR_SERVER_VOLSERLOG_FILEPATH); if (osdvol) (osdvol->op_osd_5min_check)(); #ifdef AFS_DEMAND_ATTACH_FS if (VInit >= 2) { /* look for newly mounted partitions */ VAttachPartitions(); VInitAttachVolumes(fileServer); } #endif } } return NULL; }
void _ObtainTwoLocks(struct Lock *lock1, int how1, struct Lock *lock2, int how2) { struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 1000; start: ObtainOneLock(lock1, how1); if (WillBlock(lock2, how2)) { ReleaseOneLock(lock1, how1); IOMGR_Select(0, 0, 0, 0, &timeout); goto start; } else { ObtainOneLock(lock2, how2); } }
static void SelectConsumer(void *foo) { char str[200]; int len ; fd_set readset; while(1) { FD_ZERO(&readset); if (pipa[0] >= FD_SETSIZE) errx (1, "fd too large"); FD_SET(pipa[0], &readset); IOMGR_Select(pipa[0] + 1, &readset, NULL, NULL, NULL); len = read(pipa[0], str, 199); if (len < 0) err(1, "read"); str[len] = '\0'; printf("[selcomsu] %s\n", str); } }
int SSAMPLE_Trun(struct rx_call *call) { afs_int32 code; struct ubik_trans *tt; struct timeval tv; /* truncation operation requires a write transaction, too */ code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt); if (code) return code; printf("about to set lock\n"); /* lock the database */ code = ubik_SetLock(tt, 1, 1, LOCKWRITE); printf("now have lock\n"); if (code) { ubik_AbortTrans(tt); return code; } if (sleepTime) { tv.tv_sec = sleepTime; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif } /* shrink the file */ code = ubik_Truncate(tt, 0); if (code) { ubik_AbortTrans(tt); return code; } /* commit */ code = ubik_EndTrans(tt); return code; }
void sendTest(int sockFD, int delay, int reqOOB, int size) { char *buf, *bufTest; fd_set *rfds, *wfds, *efds; int i, j; int nbytes, code; selcmd_t selCmd; time_t stime, etime; buf = (char *)malloc(size); assert(buf); bufTest = (char *)malloc(size); assert(bufTest); for (j = i = 0; i < size; i++, j++) { if (j == END_DATA) j++; if (j > 255) j = 0; buf[i] = (char)j; } selCmd.sc_cmd = SC_WRITE; selCmd.sc_info = size; selCmd.sc_delay = delay; selCmd.sc_flags = SC_WAIT_ONLY; nbytes = write(sockFD, (char *)&selCmd, sizeof(selCmd)); assert(nbytes == sizeof(selCmd)); Log("Starting to write %d bytes.\n", size); if (!delay) { nbytes = write(sockFD, buf, size); assert(nbytes == size); } else { rfds = IOMGR_AllocFDSet(); wfds = IOMGR_AllocFDSet(); efds = IOMGR_AllocFDSet(); if (!rfds || !wfds || !efds) { printf("%s: Could not allocate all fd_sets.\n", program); exit(1); } for (writeIndex = i = 0; i < size; writeIndex++, i++) { FD_ZERO(rfds); FD_ZERO(wfds); FD_ZERO(efds); FD_SET(sockFD, wfds); FD_SET(sockFD, efds); (void)time(&stime); code = IOMGR_Select(sockFD + 1, rfds, wfds, efds, (struct timeval *)NULL); assert(code > 0); if (FD_ISSET(sockFD, wfds)) { (void)time(&etime); if (etime - stime > 1) { Log("Waited %d seconds to write at offset %d.\n", etime - stime, i); } stime = etime; nbytes = write(sockFD, &buf[i], 1); (void)time(&etime); if (etime - stime > 1) { Log("Waited %d seconds IN write.\n", etime - stime); } assert(nbytes == 1); FD_CLR(sockFD, wfds); } assertNullFDSet(0, rfds); assertNullFDSet(0, wfds); assertNullFDSet(0, efds); } } Log("Wrote %d bytes.\n", size); i = 0; while (i < size) { nbytes = read(sockFD, &bufTest[i], size); i += nbytes; } Log("Read %d bytes.\n", size); assert(memcmp(buf, bufTest, size) == 0); Log("Compared %d bytes.\n", size); }
/*! * \brief Main interaction loop for the recovery manager * * The recovery light-weight process only runs when you're the * synchronization site. It performs the following tasks, if and only * if the prerequisite tasks have been performed successfully (it * keeps track of which ones have been performed in its bit map, * \p urecovery_state). * * First, it is responsible for probing that all servers are up. This * is the only operation that must be performed even if this is not * yet the sync site, since otherwise this site may not notice that * enough other machines are running to even elect this guy to be the * sync site. * * After that, the recovery process does nothing until the beacon and * voting modules manage to get this site elected sync site. * * After becoming sync site, recovery first attempts to find the best * database available in the network (it must do this in order to * ensure finding the latest committed data). After finding the right * database, it must fetch this dbase to the sync site. * * After fetching the dbase, it relabels it with a new version number, * to ensure that everyone recognizes this dbase as the most recent * dbase. * * One the dbase has been relabelled, this machine can start handling * requests. However, the recovery module still has one more task: * propagating the dbase out to everyone who is up in the network. */ void * urecovery_Interact(void *dummy) { afs_int32 code, tcode; struct ubik_server *bestServer = NULL; struct ubik_server *ts; int dbok, doingRPC, now; afs_int32 lastProbeTime; /* if we're the sync site, the best db version we've found yet */ static struct ubik_version bestDBVersion; struct ubik_version tversion; struct timeval tv; int length, tlen, offset, file, nbytes; struct rx_call *rxcall; char tbuffer[1024]; struct ubik_stat ubikstat; struct in_addr inAddr; char hoststr[16]; char pbuffer[1028]; int fd = -1; afs_int32 pass; afs_pthread_setname_self("recovery"); /* otherwise, begin interaction */ urecovery_state = 0; lastProbeTime = 0; while (1) { /* Run through this loop every 4 seconds */ tv.tv_sec = 4; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif ubik_dprint("recovery running in state %x\n", urecovery_state); /* Every 30 seconds, check all the down servers and mark them * as up if they respond. When a server comes up or found to * not be current, then re-find the the best database and * propogate it. */ if ((now = FT_ApproxTime()) > 30 + lastProbeTime) { for (ts = ubik_servers, doingRPC = 0; ts; ts = ts->next) { UBIK_BEACON_LOCK; if (!ts->up) { UBIK_BEACON_UNLOCK; doingRPC = 1; code = DoProbe(ts); if (code == 0) { UBIK_BEACON_LOCK; ts->up = 1; UBIK_BEACON_UNLOCK; DBHOLD(ubik_dbase); urecovery_state &= ~UBIK_RECFOUNDDB; DBRELE(ubik_dbase); } } else { UBIK_BEACON_UNLOCK; DBHOLD(ubik_dbase); if (!ts->currentDB) urecovery_state &= ~UBIK_RECFOUNDDB; DBRELE(ubik_dbase); } } if (doingRPC) now = FT_ApproxTime(); lastProbeTime = now; } /* Mark whether we are the sync site */ DBHOLD(ubik_dbase); if (!ubeacon_AmSyncSite()) { urecovery_state &= ~UBIK_RECSYNCSITE; DBRELE(ubik_dbase); continue; /* nothing to do */ } urecovery_state |= UBIK_RECSYNCSITE; /* If a server has just come up or if we have not found the * most current database, then go find the most current db. */ if (!(urecovery_state & UBIK_RECFOUNDDB)) { DBRELE(ubik_dbase); bestServer = (struct ubik_server *)0; bestDBVersion.epoch = 0; bestDBVersion.counter = 0; for (ts = ubik_servers; ts; ts = ts->next) { UBIK_BEACON_LOCK; if (!ts->up) { UBIK_BEACON_UNLOCK; continue; /* don't bother with these guys */ } UBIK_BEACON_UNLOCK; if (ts->isClone) continue; UBIK_ADDR_LOCK; code = DISK_GetVersion(ts->disk_rxcid, &ts->version); UBIK_ADDR_UNLOCK; if (code == 0) { /* perhaps this is the best version */ if (vcmp(ts->version, bestDBVersion) > 0) { /* new best version */ bestDBVersion = ts->version; bestServer = ts; } } } /* take into consideration our version. Remember if we, * the sync site, have the best version. Also note that * we may need to send the best version out. */ DBHOLD(ubik_dbase); if (vcmp(ubik_dbase->version, bestDBVersion) >= 0) { bestDBVersion = ubik_dbase->version; bestServer = (struct ubik_server *)0; urecovery_state |= UBIK_RECHAVEDB; } else { /* Clear the flag only when we know we have to retrieve * the db. Because urecovery_AllBetter() looks at it. */ urecovery_state &= ~UBIK_RECHAVEDB; } urecovery_state |= UBIK_RECFOUNDDB; urecovery_state &= ~UBIK_RECSENTDB; } if (!(urecovery_state & UBIK_RECFOUNDDB)) { DBRELE(ubik_dbase); continue; /* not ready */ } /* If we, the sync site, do not have the best db version, then * go and get it from the server that does. */ if ((urecovery_state & UBIK_RECHAVEDB) || !bestServer) { urecovery_state |= UBIK_RECHAVEDB; } else { /* we don't have the best version; we should fetch it. */ urecovery_AbortAll(ubik_dbase); /* Rx code to do the Bulk fetch */ file = 0; offset = 0; UBIK_ADDR_LOCK; rxcall = rx_NewCall(bestServer->disk_rxcid); ubik_print("Ubik: Synchronize database with server %s\n", afs_inet_ntoa_r(bestServer->addr[0], hoststr)); UBIK_ADDR_UNLOCK; code = StartDISK_GetFile(rxcall, file); if (code) { ubik_dprint("StartDiskGetFile failed=%d\n", code); goto FetchEndCall; } nbytes = rx_Read(rxcall, (char *)&length, sizeof(afs_int32)); length = ntohl(length); if (nbytes != sizeof(afs_int32)) { ubik_dprint("Rx-read length error=%d\n", code = BULK_ERROR); code = EIO; goto FetchEndCall; } /* give invalid label during file transit */ UBIK_VERSION_LOCK; tversion.epoch = 0; code = (*ubik_dbase->setlabel) (ubik_dbase, file, &tversion); UBIK_VERSION_UNLOCK; if (code) { ubik_dprint("setlabel io error=%d\n", code); goto FetchEndCall; } snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); fd = open(pbuffer, O_CREAT | O_RDWR | O_TRUNC, 0600); if (fd < 0) { code = errno; goto FetchEndCall; } code = lseek(fd, HDRSIZE, 0); if (code != HDRSIZE) { close(fd); goto FetchEndCall; } pass = 0; while (length > 0) { tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length); #ifndef AFS_PTHREAD_ENV if (pass % 4 == 0) IOMGR_Poll(); #endif nbytes = rx_Read(rxcall, tbuffer, tlen); if (nbytes != tlen) { ubik_dprint("Rx-read bulk error=%d\n", code = BULK_ERROR); code = EIO; close(fd); goto FetchEndCall; } nbytes = write(fd, tbuffer, tlen); pass++; if (nbytes != tlen) { code = UIOERROR; close(fd); goto FetchEndCall; } offset += tlen; length -= tlen; } code = close(fd); if (code) goto FetchEndCall; code = EndDISK_GetFile(rxcall, &tversion); FetchEndCall: tcode = rx_EndCall(rxcall, code); if (!code) code = tcode; if (!code) { /* we got a new file, set up its header */ urecovery_state |= UBIK_RECHAVEDB; UBIK_VERSION_LOCK; memcpy(&ubik_dbase->version, &tversion, sizeof(struct ubik_version)); snprintf(tbuffer, sizeof(tbuffer), "%s.DB%s%d", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); #ifdef AFS_NT40_ENV snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); code = unlink(pbuffer); if (!code) code = rename(tbuffer, pbuffer); snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.TMP", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); #endif if (!code) code = rename(pbuffer, tbuffer); if (!code) { (*ubik_dbase->open) (ubik_dbase, file); /* after data is good, sync disk with correct label */ code = (*ubik_dbase->setlabel) (ubik_dbase, 0, &ubik_dbase->version); } UBIK_VERSION_UNLOCK; #ifdef AFS_NT40_ENV snprintf(pbuffer, sizeof(pbuffer), "%s.DB%s%d.OLD", ubik_dbase->pathName, (file<0)?"SYS":"", (file<0)?-file:file); unlink(pbuffer); #endif } if (code) { unlink(pbuffer); /* * We will effectively invalidate the old data forever now. * Unclear if we *should* but we do. */ UBIK_VERSION_LOCK; ubik_dbase->version.epoch = 0; ubik_dbase->version.counter = 0; UBIK_VERSION_UNLOCK; ubik_print("Ubik: Synchronize database failed (error = %d)\n", code); } else { ubik_print("Ubik: Synchronize database completed\n"); urecovery_state |= UBIK_RECHAVEDB; } udisk_Invalidate(ubik_dbase, 0); /* data has changed */ #ifdef AFS_PTHREAD_ENV CV_BROADCAST(&ubik_dbase->version_cond); #else LWP_NoYieldSignal(&ubik_dbase->version); #endif } if (!(urecovery_state & UBIK_RECHAVEDB)) { DBRELE(ubik_dbase); continue; /* not ready */ } /* If the database was newly initialized, then when we establish quorum, write * a new label. This allows urecovery_AllBetter() to allow access for reads. * Setting it to 2 also allows another site to come along with a newer * database and overwrite this one. */ if (ubik_dbase->version.epoch == 1) { urecovery_AbortAll(ubik_dbase); UBIK_VERSION_LOCK; version_globals.ubik_epochTime = 2; ubik_dbase->version.epoch = version_globals.ubik_epochTime; ubik_dbase->version.counter = 1; code = (*ubik_dbase->setlabel) (ubik_dbase, 0, &ubik_dbase->version); UBIK_VERSION_UNLOCK; udisk_Invalidate(ubik_dbase, 0); /* data may have changed */ #ifdef AFS_PTHREAD_ENV CV_BROADCAST(&ubik_dbase->version_cond); #else LWP_NoYieldSignal(&ubik_dbase->version); #endif } /* Check the other sites and send the database to them if they * do not have the current db. */ if (!(urecovery_state & UBIK_RECSENTDB)) { /* now propagate out new version to everyone else */ dbok = 1; /* start off assuming they all worked */ /* * Check if a write transaction is in progress. We can't send the * db when a write is in progress here because the db would be * obsolete as soon as it goes there. Also, ops after the begin * trans would reach the recepient and wouldn't find a transaction * pending there. Frankly, I don't think it's possible to get past * the write-lock above if there is a write transaction in progress, * but then, it won't hurt to check, will it? */ if (ubik_dbase->flags & DBWRITING) { struct timeval tv; int safety = 0; long cur_usec = 50000; while ((ubik_dbase->flags & DBWRITING) && (safety < 500)) { DBRELE(ubik_dbase); /* sleep for a little while */ tv.tv_sec = 0; tv.tv_usec = cur_usec; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif cur_usec += 10000; safety++; DBHOLD(ubik_dbase); } } for (ts = ubik_servers; ts; ts = ts->next) { UBIK_ADDR_LOCK; inAddr.s_addr = ts->addr[0]; UBIK_ADDR_UNLOCK; UBIK_BEACON_LOCK; if (!ts->up) { UBIK_BEACON_UNLOCK; ubik_dprint("recovery cannot send version to %s\n", afs_inet_ntoa_r(inAddr.s_addr, hoststr)); dbok = 0; continue; } UBIK_BEACON_UNLOCK; ubik_dprint("recovery sending version to %s\n", afs_inet_ntoa_r(inAddr.s_addr, hoststr)); if (vcmp(ts->version, ubik_dbase->version) != 0) { ubik_dprint("recovery stating local database\n"); /* Rx code to do the Bulk Store */ code = (*ubik_dbase->stat) (ubik_dbase, 0, &ubikstat); if (!code) { length = ubikstat.size; file = offset = 0; UBIK_ADDR_LOCK; rxcall = rx_NewCall(ts->disk_rxcid); UBIK_ADDR_UNLOCK; code = StartDISK_SendFile(rxcall, file, length, &ubik_dbase->version); if (code) { ubik_dprint("StartDiskSendFile failed=%d\n", code); goto StoreEndCall; } while (length > 0) { tlen = (length > sizeof(tbuffer) ? sizeof(tbuffer) : length); nbytes = (*ubik_dbase->read) (ubik_dbase, file, tbuffer, offset, tlen); if (nbytes != tlen) { ubik_dprint("Local disk read error=%d\n", code = UIOERROR); goto StoreEndCall; } nbytes = rx_Write(rxcall, tbuffer, tlen); if (nbytes != tlen) { ubik_dprint("Rx-write bulk error=%d\n", code = BULK_ERROR); goto StoreEndCall; } offset += tlen; length -= tlen; } code = EndDISK_SendFile(rxcall); StoreEndCall: code = rx_EndCall(rxcall, code); } if (code == 0) { /* we set a new file, process its header */ ts->version = ubik_dbase->version; ts->currentDB = 1; } else dbok = 0; } else { /* mark file up to date */ ts->currentDB = 1; } } if (dbok) urecovery_state |= UBIK_RECSENTDB; } DBRELE(ubik_dbase); } return NULL; }
static void * SocketListener(void *unused) { fd_set rfds; struct timeval tv; struct packet packet; socklen_t fromLen; afs_int32 code; char hoststr[16]; printf("Starting to listen for UDP packets\n"); while (1) { FD_ZERO(&rfds); if (sock_kerb >= 0) FD_SET(sock_kerb, &rfds); if (sock_kerb5 >= 0) FD_SET(sock_kerb5, &rfds); tv.tv_sec = 100; tv.tv_usec = 0; /* write and exception fd_set's are null */ code = IOMGR_Select(32, &rfds, NULL, NULL, &tv); if (code == 0) { /* timeout */ /* printf ("Timeout\n"); */ continue; } else if (code < 0) { perror("calling IOMGR_Select"); break; } fromLen = sizeof(packet.from); if ((sock_kerb >= 0) && FD_ISSET(sock_kerb, &rfds)) { code = recvfrom(sock_kerb, packet.data, sizeof(packet.data), 0, (struct sockaddr *)&packet.from, &fromLen); if (code < 0) { if (errno == EAGAIN || errno == ECONNREFUSED) goto try_kerb5; perror("calling recvfrom"); break; } packet.len = code; if (krb_udp_debug) { printf("Kerb:udp: Got %d bytes from addr %s which are '", code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr)); ka_PrintBytes(packet.data, packet.len); printf("'\n"); } packet.name = packet.inst = packet.realm = ""; packet.time = 0; process_udp_request(sock_kerb, &packet); } try_kerb5: if ((sock_kerb5 >= 0) && FD_ISSET(sock_kerb5, &rfds)) { code = recvfrom(sock_kerb5, packet.data, sizeof(packet.data), 0, (struct sockaddr *)&packet.from, &fromLen); if (code < 0) { if (errno == EAGAIN || errno == ECONNREFUSED) continue; perror("calling recvfrom"); break; } packet.len = code; if (krb_udp_debug) { printf("Kerb5:udp: Got %d bytes from addr %s which are '", code, afs_inet_ntoa_r(packet.from.sin_addr.s_addr, hoststr)); ka_PrintBytes(packet.data, packet.len); printf("'\n"); } packet.name = packet.inst = packet.realm = ""; packet.time = 0; process_udp_request(sock_kerb5, &packet); } } if (sock_kerb >= 0) { closesocket(sock_kerb); sock_kerb = -1; } if (sock_kerb5 >= 0) { closesocket(sock_kerb5); sock_kerb5 = -1; } printf("UDP SocketListener exiting due to error\n"); return NULL; }
void handleWrite(clientHandle_t * ch, selcmd_t * sc) { int i; fd_set *rfds, *wfds, *efds; char *buf; int code; int scode; char c; int nbytes; rfds = IOMGR_AllocFDSet(); wfds = IOMGR_AllocFDSet(); efds = IOMGR_AllocFDSet(); assert(rfds && wfds && efds); if (sc->sc_delay > 0) { IOMGR_Sleep(sc->sc_delay); } Log("(handleWrite 0x%x) waking after %d second sleep.\n", ch->ch_pid, sc->sc_delay); if (sc->sc_flags & SC_WAIT_OOB) sendOOB(ch->ch_fd); buf = (char *)malloc(sc->sc_info); assert(buf); i = 0; while (1) { FD_ZERO(rfds); FD_SET(ch->ch_fd, rfds); FD_ZERO(efds); FD_SET(ch->ch_fd, efds); FD_ZERO(wfds); scode = IOMGR_Select(ch->ch_fd + 1, rfds, wfds, efds, (struct timeval *)0); assert(scode > 0); if (FD_ISSET(ch->ch_fd, rfds)) { assert(i < sc->sc_info); code = read(ch->ch_fd, &buf[i], 1); i++; write_I++; if (code != 1) { Log("code =%d\n", code); assert(code == 1); } /* Test for valid fds */ assertNullFDSet(ch->ch_fd, rfds); assertNullFDSet(-1, wfds); assertNullFDSet(-1, efds); if (c == END_DATA || i >= sc->sc_info) { break; } } } Log("Read %d bytes of data.\n", sc->sc_info); nbytes = write(ch->ch_fd, buf, sc->sc_info); assert(nbytes == sc->sc_info); Log("Wrote data back to client.\n"); IOMGR_FreeFDSet(rfds); IOMGR_FreeFDSet(wfds); IOMGR_FreeFDSet(efds); }
void handleRequest(char *arg) { clientHandle_t *ch = (clientHandle_t *) arg; selcmd_t sc; struct stat sbuf; int code = 0; int c_errno = 0; while (1) { Log("(handleRequest) going to sleep on 0x%x\n", &ch->ch_state); LWP_WaitProcess(&ch->ch_state); assert(ch->ch_state == CH_INUSE); FD_ZERO(&(ch->ch_read)); FD_ZERO(&(ch->ch_write)); FD_ZERO(&(ch->ch_except)); FD_SET(ch->ch_fd, &(ch->ch_read)); FD_SET(ch->ch_fd, &(ch->ch_except)); code = IOMGR_Select(ch->ch_fd + 1, &(ch->ch_read), &(ch->ch_write), &(ch->ch_except), (struct timeval *)NULL); if (FD_ISSET(ch->ch_fd, &(ch->ch_except))) { Log("Received expception. Read fd_set shows %d\n", FD_ISSET(ch->ch_fd, &(ch->ch_read))); assertNullFDSet(ch->ch_fd, &(ch->ch_read)); assertNullFDSet(-1, &(ch->ch_write)); assertNullFDSet(ch->ch_fd, &(ch->ch_except)); goto done; } assert(code > 0); if (read(ch->ch_fd, (char *)&sc, sizeof(sc)) != sizeof(sc)) { Die(1, "(handleRequest) read command"); } Log("(handleRequest)cmd=%d\n", sc.sc_cmd); fflush(stdout); switch (sc.sc_cmd) { case SC_PROBE: Log("Probed from client at %s\n", inet_ntoa(ch->ch_addr.sin_addr)); break; #ifdef notdef case SC_OOB: nThreads--; ch->ch_fd = 0; ch->ch_state = CH_FREE; return; #endif case SC_WRITE: handleWrite(ch, &sc); break; case SC_END: Log("Ending ungracefully in server.\n"); exit(1); default: Log("%d: bad command to handleRequest.\n", sc.sc_cmd); break; } done: /* We're done now, so we can be re-used. */ nThreads--; close(ch->ch_fd); ch->ch_fd = 0; ch->ch_state = CH_FREE; } }
main(int ac, char **av) { int i; int on = 1; short port = -1; /* host order. */ int setFD = 0; struct sockaddr_in saddr; int acceptFD; clientHandle_t *clientHandle; int code; int addr_len; PROCESS pid; fd_set *rfds, *wfds, *efds; int sockFD; program = av[0]; if (ac < 2) Usage(); /* lwp_debug = 1; */ signal(SIGIO, sigIO); for (i = 1; i < ac; i++) { if (!strcmp("-fd", av[i])) { if (++i >= ac) { printf("Missing number for -fd option.\n"); Usage(); } setFD = atoi(av[i]); if (setFD <= 2) { printf("%d: file descriptor must be at least 3.\n", setFD); Usage(); } } else { if (port == -1) { port = atoi(av[i]); if (port <= 0) { printf("%s: port must be at least 1\n", av[i]); Usage(); } } else { printf("%s: Unknown argument.\n", av[i]); } } } if (port == -1) { printf("Missing port.\n"); Usage(); } if (!setFD) { setFD = 31; printf("Using default socket of %d.\n", setFD); } OpenFDs(setFD); IOMGR_Initialize(); /* Setup server processes */ for (i = 0; i < MAX_THREADS; i++) { if (LWP_CreateProcess (handleRequest, 32768, LWP_NORMAL_PRIORITY, (char *)&clientHandles[i], "HandleRequestThread", &pid) < 0) { printf("%s: Failed to start all LWP's\n", program); exit(1); } clientHandles[i].ch_pid = pid; } sockFD = socket(AF_INET, SOCK_STREAM, 0); if (sockFD < 0) { perror("socket"); exit(1); } Log("Using socket at file descriptor %d.\n", sockFD); if (setsockopt(sockFD, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { perror("setsockopt: "); exit(1); } memset((void *)&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = ntohs(port); saddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(sockFD, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { perror("bind: "); exit(1); } rfds = IOMGR_AllocFDSet(); wfds = IOMGR_AllocFDSet(); efds = IOMGR_AllocFDSet(); if (!rfds || !wfds || !efds) { printf("main: Could not alloc fd_set's.\n"); exit(1); } listen(sockFD, 100); while (1) { FD_ZERO(rfds); FD_ZERO(wfds); FD_ZERO(efds); FD_SET(sockFD, rfds); FD_SET(sockFD, efds); Log("Main - going to select.\n"); code = IOMGR_Select(sockFD + 1, rfds, wfds, efds, (struct timeval *)0); switch (code) { case 0: /* Timer, can't happen here. */ case -1: case -2: Log("Oops! select returns %d!\n", code); abort(); default: if (FD_ISSET(sockFD, efds)) { recvOOB(sockFD); assertNullFDSet(sockFD, rfds); assertNullFDSet(-1, wfds); assertNullFDSet(sockFD, efds); } if (FD_ISSET(sockFD, rfds)) { while (nThreads > MAX_THREADS) { IOMGR_Sleep(1); } clientHandle = getClientHandle(); addr_len = sizeof(clientHandle->ch_addr); clientHandle->ch_fd = accept(sockFD, (struct sockaddr *) &clientHandle->ch_addr, &addr_len); if (clientHandle->ch_fd < 0) { perror("accept: "); exit(1); } Log("Main - signalling LWP 0x%x\n", &clientHandle->ch_state); LWP_NoYieldSignal(&clientHandle->ch_state); assertNullFDSet(sockFD, rfds); assertNullFDSet(-1, wfds); assertNullFDSet(-1, efds); break; } Die(1, "(main) No data to read.\n"); } } }
static void * xstat_fs_LWP(void *unused) { static char rn[] = "xstat_fs_LWP"; /*Routine name */ afs_int32 code; /*Results of calls */ int oneShotCode; /*Result of one-shot signal */ struct timeval tv; /*Time structure */ int conn_idx; /*Connection index */ struct xstat_fs_ConnectionInfo *curr_conn; /*Current connection */ afs_int32 srvVersionNumber; /*Xstat version # */ afs_int32 clientVersionNumber; /*Client xstat version */ afs_int32 numColls; /*Number of collections to get */ afs_int32 *currCollIDP; /*Curr collection ID desired */ /* * Set up some numbers we'll need. */ clientVersionNumber = AFS_XSTAT_VERSION; while (1) { /*Service loop */ /* * Iterate through the server connections, gathering data. * Don't forget to bump the probe count and zero the statistics * areas before calling the servers. */ if (xstat_fs_debug) printf("[%s] Waking up, getting data from %d server(s)\n", rn, xstat_fs_numServers); curr_conn = xstat_fs_ConnInfo; xstat_fs_Results.probeNum++; for (conn_idx = 0; conn_idx < xstat_fs_numServers; conn_idx++) { /* * Grab the statistics for the current File Server, if the * connection is valid. */ if (xstat_fs_debug) printf("[%s] Getting collections from File Server '%s'\n", rn, curr_conn->hostName); if (curr_conn->rxconn != (struct rx_connection *)0) { if (xstat_fs_debug) printf("[%s] Connection OK, calling RXAFS_GetXStats\n", rn); currCollIDP = xstat_fs_collIDP; for (numColls = 0; numColls < xstat_fs_numCollections; numColls++, currCollIDP++) { /* * Initialize the per-probe values. */ if (xstat_fs_debug) printf("[%s] Asking for data collection %d\n", rn, *currCollIDP); xstat_fs_Results.collectionNumber = *currCollIDP; xstat_fs_Results.data.AFS_CollData_len = AFS_MAX_XSTAT_LONGS; memset(xstat_fs_Results.data.AFS_CollData_val, 0, AFS_MAX_XSTAT_LONGS * 4); xstat_fs_Results.connP = curr_conn; if (xstat_fs_debug) { printf ("%s: Calling RXAFS_GetXStats, conn=%" AFS_PTR_FMT ", clientVersionNumber=%d, collectionNumber=%d, srvVersionNumberP=%" AFS_PTR_FMT ", timeP=%" AFS_PTR_FMT ", dataP=%" AFS_PTR_FMT "\n", rn, curr_conn->rxconn, clientVersionNumber, *currCollIDP, &srvVersionNumber, &(xstat_fs_Results.probeTime), &(xstat_fs_Results.data)); printf("%s: [bufflen=%d, buffer at %" AFS_PTR_FMT "]\n", rn, xstat_fs_Results.data.AFS_CollData_len, xstat_fs_Results.data.AFS_CollData_val); } xstat_fs_Results.probeOK = RXAFS_GetXStats(curr_conn->rxconn, clientVersionNumber, *currCollIDP, &srvVersionNumber, &(xstat_fs_Results.probeTime), &(xstat_fs_Results.data)); /* * Now that we (may) have the data for this connection, * call the associated handler function. The handler does * not take any explicit parameters, but rather gets to the * goodies via some of the objects exported by this module. */ if (xstat_fs_debug) printf("[%s] Calling handler routine.\n", rn); code = xstat_fs_Handler(); if (code) fprintf(stderr, "[%s] Handler returned error code %d\n", rn, code); } /*For each collection */ } /*Valid Rx connection */ /* * Advance the xstat_fs connection pointer. */ curr_conn++; } /*For each xstat_fs connection */ /* * All (valid) connections have been probed. Fall asleep for the * prescribed number of seconds, unless we're a one-shot. In * that case, we need to signal our caller that we're done. */ if (xstat_fs_debug) printf("[%s] Polling complete for probe round %d.\n", rn, xstat_fs_Results.probeNum); if (xstat_fs_oneShot) { /* * One-shot execution desired. Signal our main procedure * that we've finished our collection round. */ if (xstat_fs_debug) printf("[%s] Signalling main process at %" AFS_PTR_FMT "\n", rn, &terminationEvent); oneShotCode = LWP_SignalProcess(&terminationEvent); if (oneShotCode) fprintf(stderr, "[%s] Error %d from LWP_SignalProcess()", rn, oneShotCode); break; /*from the perpetual while loop */ } /*One-shot execution */ else { /* * Continuous execution desired. Sleep for the required * number of seconds. */ tv.tv_sec = xstat_fs_ProbeFreqInSecs; tv.tv_usec = 0; if (xstat_fs_debug) printf("[%s] Falling asleep for %d seconds\n", rn, xstat_fs_ProbeFreqInSecs); code = IOMGR_Select(0, /*Num fids */ 0, /*Descs ready for reading */ 0, /*Descs ready for writing */ 0, /*Descs w/exceptional conditions */ &tv); /*Ptr to timeout structure */ if (code) fprintf(stderr, "[%s] IOMGR_Select returned code %d\n", rn, code); } /*Continuous execution */ } /*Service loop */ return NULL; }
static void rxi_ListenerProc(fd_set * rfds, int *tnop, struct rx_call **newcallp) { afs_uint32 host; u_short port; struct rx_packet *p = (struct rx_packet *)0; osi_socket socket; struct clock cv; afs_int32 nextPollTime; /* time to next poll FD before sleeping */ int lastPollWorked, doingPoll; /* true iff last poll was useful */ struct timeval tv, *tvp; int code; #ifdef AFS_NT40_ENV int i; #endif PROCESS pid; char name[MAXTHREADNAMELENGTH] = "srv_0"; clock_NewTime(); lastPollWorked = 0; nextPollTime = 0; code = LWP_CurrentProcess(&pid); if (code) { fprintf(stderr, "rxi_Listener: Can't get my pid.\n"); exit(1); } rx_listenerPid = pid; if (swapNameProgram) (*swapNameProgram) (pid, "listener", &name[0]); for (;;) { /* Grab a new packet only if necessary (otherwise re-use the old one) */ if (p) { rxi_RestoreDataBufs(p); } else { if (!(p = rxi_AllocPacket(RX_PACKET_CLASS_RECEIVE))) osi_Panic("rxi_ListenerProc: no packets!"); /* Shouldn't happen */ } /* Wait for the next event time or a packet to arrive. */ /* event_RaiseEvents schedules any events whose time has come and * then atomically computes the time to the next event, guaranteeing * that this is positive. If there is no next event, it returns 0 */ clock_NewTime(); if (!rxevent_RaiseEvents(&cv)) tvp = NULL; else { /* It's important to copy cv to tv, because the 4.3 documentation * for select threatens that *tv may be updated after a select, in * future editions of the system, to indicate how much of the time * period has elapsed. So we shouldn't rely on tv not being altered. */ tv.tv_sec = cv.sec; /* Time to next event */ tv.tv_usec = cv.usec; tvp = &tv; } rx_AtomicIncrement(rx_stats.selects, rx_stats_mutex); *rfds = rx_selectMask; if (lastPollWorked || nextPollTime < clock_Sec()) { /* we're catching up, or haven't tried to for a few seconds */ doingPoll = 1; nextPollTime = clock_Sec() + 4; /* try again in 4 seconds no matter what */ tv.tv_sec = tv.tv_usec = 0; /* make sure we poll */ tvp = &tv; code = select((int)(rx_maxSocketNumber + 1), rfds, 0, 0, tvp); } else { doingPoll = 0; code = IOMGR_Select((int)(rx_maxSocketNumber + 1), rfds, 0, 0, tvp); } lastPollWorked = 0; /* default is that it didn't find anything */ if (quitListening) { quitListening = 0; LWP_DestroyProcess(pid); } switch (code) { case 0: /* Timer interrupt: * If it was a timer interrupt then we can assume that * the time has advanced by roughly the value of the * previous timeout, and that there is now at least * one pending event. */ clock_NewTime(); break; case -1: /* select or IOMGR_Select returned failure */ debugSelectFailure++; /* update debugging counter */ clock_NewTime(); break; case -2: /* IOMGR_Cancel: * IOMGR_Cancel is invoked whenever a new event is * posted that is earlier than any existing events. * So we re-evaluate the time, and then go back to * reschedule events */ clock_NewTime(); break; default: /* Packets have arrived, presumably: * If it wasn't a timer interrupt, then no event should have * timed out yet (well some event may have, but only just...), so * we don't bother looking to see if any have timed out, but just * go directly to reading the data packets */ clock_NewTime(); if (doingPoll) lastPollWorked = 1; #ifdef AFS_NT40_ENV for (i = 0; p && i < rfds->fd_count; i++) { socket = rfds->fd_array[i]; if (rxi_ReadPacket(socket, p, &host, &port)) { *newcallp = NULL; p = rxi_ReceivePacket(p, socket, host, port, tnop, newcallp); if (newcallp && *newcallp) { if (p) { rxi_FreePacket(p); } if (swapNameProgram) { (*swapNameProgram) (rx_listenerPid, name, 0); rx_listenerPid = 0; } return; } } } #else for (socket = rx_minSocketNumber; p && socket <= rx_maxSocketNumber; socket++) { if (!FD_ISSET(socket, rfds)) continue; if (rxi_ReadPacket(socket, p, &host, &port)) { p = rxi_ReceivePacket(p, socket, host, port, tnop, newcallp); if (newcallp && *newcallp) { if (p) { rxi_FreePacket(p); } if (swapNameProgram) { (*swapNameProgram) (rx_listenerPid, name, 0); rx_listenerPid = 0; } return; } } } #endif break; } } /* NOTREACHED */ }
/* bnode lwp executes this code repeatedly */ static void * bproc(void *unused) { afs_int32 code; struct bnode *tb; afs_int32 temp; struct bnode_proc *tp; struct bnode *nb; int options; /* must not be register */ struct timeval tv; int setAny; int status; while (1) { /* first figure out how long to sleep for */ temp = 0x7fffffff; /* afs_int32 time; maxint doesn't work in select */ setAny = 0; for (tb = allBnodes; tb; tb = tb->next) { if (tb->flags & BNODE_NEEDTIMEOUT) { if (tb->nextTimeout < temp) { setAny = 1; temp = tb->nextTimeout; } } } /* now temp has the time at which we should wakeup next */ /* sleep */ if (setAny) temp -= FT_ApproxTime(); /* how many seconds until next event */ else temp = 999999; if (temp > 0) { tv.tv_sec = temp; tv.tv_usec = 0; code = IOMGR_Select(0, 0, 0, 0, &tv); } else code = 0; /* fake timeout code */ /* figure out why we woke up; child exit or timeouts */ FT_GetTimeOfDay(&tv, 0); /* must do the real gettimeofday once and a while */ temp = tv.tv_sec; /* check all bnodes to see which ones need timeout events */ for (tb = allBnodes; tb; tb = nb) { if ((tb->flags & BNODE_NEEDTIMEOUT) && temp > tb->nextTimeout) { bnode_Hold(tb); BOP_TIMEOUT(tb); bnode_Check(tb); if (tb->flags & BNODE_NEEDTIMEOUT) { /* check again, BOP_TIMEOUT could change */ tb->nextTimeout = FT_ApproxTime() + tb->period; } nb = tb->next; bnode_Release(tb); /* delete may occur here */ } else nb = tb->next; } if (code < 0) { /* signalled, probably by incoming signal */ while (1) { options = WNOHANG; bnode_waiting = options | 0x800000; code = waitpid((pid_t) - 1, &status, options); bnode_waiting = 0; if (code == 0 || code == -1) break; /* all done */ /* otherwise code has a process id, which we now search for */ for (tp = allProcs; tp; tp = tp->next) if (tp->pid == code) break; if (tp) { /* found the pid */ tb = tp->bnode; bnode_Hold(tb); /* count restarts in last 10 seconds */ if (temp > tb->rsTime + 30) { /* it's been 10 seconds we've been counting */ tb->rsTime = temp; tb->rsCount = 0; } if (WIFSIGNALED(status) == 0) { /* exited, not signalled */ tp->lastExit = WEXITSTATUS(status); tp->lastSignal = 0; if (tp->lastExit) { tb->errorCode = tp->lastExit; tb->lastErrorExit = FT_ApproxTime(); RememberProcName(tp); tb->errorSignal = 0; } if (tp->coreName) bozo_Log("%s:%s exited with code %d\n", tb->name, tp->coreName, tp->lastExit); else bozo_Log("%s exited with code %d\n", tb->name, tp->lastExit); } else { /* Signal occurred, perhaps spurious due to shutdown request. * If due to a shutdown request, don't overwrite last error * information. */ tp->lastSignal = WTERMSIG(status); tp->lastExit = 0; if (tp->lastSignal != SIGQUIT && tp->lastSignal != SIGTERM && tp->lastSignal != SIGKILL) { tb->errorSignal = tp->lastSignal; tb->lastErrorExit = FT_ApproxTime(); RememberProcName(tp); } if (tp->coreName) bozo_Log("%s:%s exited on signal %d%s\n", tb->name, tp->coreName, tp->lastSignal, WCOREDUMP(status) ? " (core dumped)" : ""); else bozo_Log("%s exited on signal %d%s\n", tb->name, tp->lastSignal, WCOREDUMP(status) ? " (core dumped)" : ""); SaveCore(tb, tp); } tb->lastAnyExit = FT_ApproxTime(); if (tb->notifier) { bozo_Log("BNODE: Notifier %s will be called\n", tb->notifier); hdl_notifier(tp); } BOP_PROCEXIT(tb, tp); bnode_Check(tb); if (tb->rsCount++ > 10) { /* 10 in 10 seconds */ tb->flags |= BNODE_ERRORSTOP; bnode_SetGoal(tb, BSTAT_SHUTDOWN); bozo_Log ("BNODE '%s' repeatedly failed to start, perhaps missing executable.\n", tb->name); } bnode_Release(tb); /* bnode delete can happen here */ DeleteProc(tp); } else bnode_stats.weirdPids++; } } } return NULL; }
int main(int argc, char **argv) { register afs_int32 code; struct ubik_client *cstruct = 0; afs_uint32 serverList[MAXSERVERS]; struct rx_connection *serverconns[MAXSERVERS]; struct rx_securityClass *sc; register afs_int32 i; afs_int32 temp; if (argc == 1) { printf ("uclient: usage is 'uclient -servers ... [-try] [-get] [-inc] [-minc] [-trunc]\n"); exit(0); } #ifdef AFS_NT40_ENV /* initialize winsock */ if (afs_winsockInit() < 0) return -1; #endif /* first parse '-servers <server-1> <server-2> ... <server-n>' from command line */ code = ubik_ParseClientList(argc, argv, serverList); if (code) { printf("could not parse server list, code %d\n", code); exit(1); } rx_Init(0); sc = rxnull_NewClientSecurityObject(); for (i = 0; i < MAXSERVERS; i++) { if (serverList[i]) { serverconns[i] = rx_NewConnection(serverList[i], htons(3000), USER_SERVICE_ID, sc, 0); } else { serverconns[i] = (struct rx_connection *)0; break; } } /* next, pass list of server rx_connections (in serverconns), and * a place to put the returned client structure that we'll use in * all of our rpc calls (via ubik_Calll) */ code = ubik_ClientInit(serverconns, &cstruct); /* check code from init */ if (code) { printf("ubik client init failed with code %d\n", code); exit(1); } /* parse command line for our own operations */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-inc")) { /* use ubik_Call to do the work, finding an up server and handling * the job of finding a sync site, if need be */ code = ubik_SAMPLE_Inc(cstruct, 0); printf("return code is %d\n", code); } else if (!strcmp(argv[i], "-try")) { code = ubik_SAMPLE_Test(cstruct, 0); printf("return code is %d\n", code); } else if (!strcmp(argv[i], "-qget")) { code = ubik_SAMPLE_QGet(cstruct, 0, &temp); printf("got quick value %d (code %d)\n", temp, code); } else if (!strcmp(argv[i], "-get")) { code = ubik_SAMPLE_Get(cstruct, 0, &temp); printf("got value %d (code %d)\n", temp, code); } else if (!strcmp(argv[i], "-trunc")) { code = ubik_SAMPLE_Trun(cstruct, 0); printf("return code is %d\n", code); } else if (!strcmp(argv[i], "-minc")) { afs_int32 temp; struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; printf("ubik_client: Running minc...\n"); while (1) { temp = 0; code = ubik_SAMPLE_Get(cstruct, 0, &temp); if (code != 0) { printf("SAMPLE_Get #1 failed with code %ld\n", afs_printable_int32_ld(code)); } else { printf("SAMPLE_Get #1 succeeded, got value %ld\n", afs_printable_int32_ld(temp)); } temp = 0; code = ubik_SAMPLE_Inc(cstruct, 0); if (code != 0) { printf("SAMPLE_Inc #1 failed with code %ld\n", afs_printable_int32_ld(code)); } else { printf("SAMPLE_Inc #1 succeeded, incremented integer\n"); } temp = 0; code = ubik_SAMPLE_Get(cstruct, 0, &temp); if (code != 0) { printf("SAMPLE_Get #2 failed with code %ld\n", afs_printable_int32_ld(code)); } else { printf("SAMPLE_Get #2 succeeded, got value %ld\n", afs_printable_int32_ld(temp)); } temp = 0; code = ubik_SAMPLE_Inc(cstruct, 0); if (code != 0) printf("SAMPLE_Inc #2 failed with code %ld\n", afs_printable_int32_ld(code)); else printf("SAMPLE_Inc #2 succeeded, incremented integer\n"); tv.tv_sec = 1; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif printf("Repeating the SAMPLE operations again...\n"); } } else if (!strcmp(argv[i], "-mget")) { afs_int32 temp; struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; while (1) { code = ubik_SAMPLE_Get(cstruct, 0, &temp); printf("got value %d (code %d)\n", temp, code); code = ubik_SAMPLE_Inc(cstruct, 0); printf("update return code is %d\n", code); code = ubik_SAMPLE_Get(cstruct, 0, &temp); printf("got value %d (code %d)\n", temp, code); code = ubik_SAMPLE_Get(cstruct, 0, &temp); printf("got value %d (code %d)\n", temp, code); tv.tv_sec = 1; tv.tv_usec = 0; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &tv); #else IOMGR_Select(0, 0, 0, 0, &tv); #endif } } } return 0; }
/*------------------------------------------------------------------------ * [private] fsprobe_LWP * * Description: * This LWP iterates over the server connections and gathers up * the desired statistics from each one on a regular basis. When * the sweep is done, the associated handler function is called * to process the new data. * * Arguments: * None. * * Returns: * Nothing. * * Environment: * Started by fsprobe_Init(), uses global sturctures. * * Side Effects: * As advertised. *------------------------------------------------------------------------*/ static void * fsprobe_LWP(void *unused) { /*fsprobe_LWP */ static char rn[] = "fsprobe_LWP"; /*Routine name */ register afs_int32 code; /*Results of calls */ struct timeval tv; /*Time structure */ int conn_idx; /*Connection index */ struct fsprobe_ConnectionInfo *curr_conn; /*Current connection */ struct ProbeViceStatistics *curr_stats; /*Current stats region */ int *curr_probeOK; /*Current probeOK field */ ViceStatistics64 stats64; /*Current stats region */ stats64.ViceStatistics64_val = (afs_uint64 *)malloc(STATS64_VERSION * sizeof(afs_uint64)); while (1) { /*Service loop */ /* * Iterate through the server connections, gathering data. * Don't forget to bump the probe count and zero the statistics * areas before calling the servers. */ if (fsprobe_debug) fprintf(stderr, "[%s] Waking up, collecting data from %d connected servers\n", rn, fsprobe_numServers); curr_conn = fsprobe_ConnInfo; curr_stats = fsprobe_Results.stats; curr_probeOK = fsprobe_Results.probeOK; fsprobe_Results.probeNum++; memset(fsprobe_Results.stats, 0, fsprobe_statsBytes); memset(fsprobe_Results.probeOK, 0, fsprobe_probeOKBytes); for (conn_idx = 0; conn_idx < fsprobe_numServers; conn_idx++) { /* * Grab the statistics for the current FileServer, if the * connection is valid. */ if (fsprobe_debug) fprintf(stderr, "[%s] Contacting server %s\n", rn, curr_conn->hostName); if (curr_conn->rxconn != (struct rx_connection *)0) { if (fsprobe_debug) fprintf(stderr, "[%s] Connection valid, calling RXAFS_GetStatistics\n", rn); *curr_probeOK = RXAFS_GetStatistics64(curr_conn->rxconn, STATS64_VERSION, &stats64); if (*curr_probeOK == RXGEN_OPCODE) *curr_probeOK = RXAFS_GetStatistics(curr_conn->rxconn, (ViceStatistics *)curr_stats); else if (*curr_probeOK == 0) { curr_stats->CurrentTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_CURRENTTIME]); curr_stats->BootTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_BOOTTIME]); curr_stats->StartTime = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_STARTTIME]); curr_stats->CurrentConnections = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_CURRENTCONNECTIONS]); curr_stats->TotalFetchs = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_TOTALFETCHES]); curr_stats->TotalStores = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_TOTALSTORES]); curr_stats->WorkStations = RoundInt64ToInt32(stats64.ViceStatistics64_val[STATS64_WORKSTATIONS]); } } /*Valid Rx connection */ /* * Call the Volume Server too to get additional stats */ if (fsprobe_debug) fprintf(stderr, "[%s] Contacting volume server %s\n", rn, curr_conn->hostName); if (curr_conn->rxVolconn != (struct rx_connection *)0) { int i, code; char pname[10]; struct diskPartition partition; struct diskPartition64 *partition64p = (struct diskPartition64 *)malloc(sizeof(struct diskPartition64)); if (fsprobe_debug) fprintf(stderr, "[%s] Connection valid, calling RXAFS_GetStatistics\n", rn); for (i = 0; i < curr_conn->partCnt; i++) { if (curr_conn->partList.partFlags[i] & PARTVALID) { MapPartIdIntoName(curr_conn->partList.partId[i], pname); code = AFSVolPartitionInfo64(curr_conn->rxVolconn, pname, partition64p); if (!code) { curr_stats->Disk[i].BlocksAvailable = RoundInt64ToInt31(partition64p->free); curr_stats->Disk[i].TotalBlocks = RoundInt64ToInt31(partition64p->minFree); strcpy(curr_stats->Disk[i].Name, pname); } if (code == RXGEN_OPCODE) { code = AFSVolPartitionInfo(curr_conn->rxVolconn, pname, &partition); if (!code) { curr_stats->Disk[i].BlocksAvailable = partition.free; curr_stats->Disk[i].TotalBlocks = partition.minFree; strcpy(curr_stats->Disk[i].Name, pname); } } if (code) { fprintf(stderr, "Could not get information on server %s partition %s\n", curr_conn->hostName, pname); } } } free(partition64p); } /* * Advance the fsprobe connection pointer & stats pointer. */ curr_conn++; curr_stats++; curr_probeOK++; } /*For each fsprobe connection */ /* * All (valid) connections have been probed. Now, call the * associated handler function. The handler does not take * any explicit parameters, rather gets to the goodies via * some of the objects exported by this module. */ if (fsprobe_debug) fprintf(stderr, "[%s] Polling complete, calling associated handler routine.\n", rn); code = fsprobe_Handler(); if (code) fprintf(stderr, "[%s] Handler routine returned error code %d\n", rn, code); /* * Fall asleep for the prescribed number of seconds. */ tv.tv_sec = fsprobe_ProbeFreqInSecs; tv.tv_usec = 0; if (fsprobe_debug) fprintf(stderr, "[%s] Falling asleep for %d seconds\n", rn, fsprobe_ProbeFreqInSecs); code = IOMGR_Select(0, /*Num fids */ 0, /*Descriptors ready for reading */ 0, /*Descriptors ready for writing */ 0, /*Descriptors w/exceptional conditions */ &tv); /*Ptr to timeout structure */ if (code) fprintf(stderr, "[%s] IOMGR_Select returned code %d\n", rn, code); } /*Service loop */ free(stats64.ViceStatistics64_val); return NULL; } /*fsprobe_LWP */