示例#1
0
文件: volmain.c 项目: openafs/openafs
/* 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));
}
示例#2
0
// 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);
}
示例#3
0
文件: ares.c 项目: ahltorp/afssync
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);
	}
    }
}
示例#4
0
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;
}
示例#5
0
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");
    }
}
示例#6
0
文件: waitkey.c 项目: bagdxk/openafs
/* 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;
}
示例#7
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);
    }
}
示例#8
0
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);
    }
}
示例#9
0
文件: db_dump.c 项目: adeason/openafs
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);
}
示例#10
0
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;
}
示例#11
0
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;
}
示例#12
0
文件: waitkey.c 项目: bagdxk/openafs
/* 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;
}
示例#13
0
文件: test.c 项目: chanke/openafs-osd
/* 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;
}
示例#14
0
文件: lock.c 项目: ahltorp/afssync
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);
    }
}
示例#15
0
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);
    }
}
示例#16
0
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;
}
示例#17
0
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);
}
示例#18
0
文件: recovery.c 项目: vkamra/openafs
/*!
 * \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;
}
示例#19
0
文件: krb_udp.c 项目: hwr/openafs
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;
}
示例#20
0
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);
}
示例#21
0
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;
    }
}
示例#22
0
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");
	}
    }
}
示例#23
0
文件: xstat_fs.c 项目: bagdxk/openafs
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;
}
示例#24
0
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 */
}
示例#25
0
/* 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;
}
示例#26
0
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;
}
示例#27
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 */