afs_uint32 xfopen_voldump(XFILE * X, struct rx_connection * conn, afs_int32 part, afs_int32 volid, afs_int32 date) { struct rx_call *call; struct rxinfo *i; afs_int32 code, rcode; afs_int32 tid; if ((code = AFSVolTransCreate(conn, volid, part, ITBusy, &tid))) return code; call = rx_NewCall(conn); if ((code = StartAFSVolDump(call, tid, date)) || (code = xfopen_rxcall(X, O_RDONLY, call))) { rx_EndCall(call, 0); AFSVolEndTrans(conn, tid, &rcode); return code; } i = X->refcon; i->conn = conn; i->tid = tid; X->do_close = xf_voldump_do_close; return 0; }
afs_int32 FetchData(char **argp) { struct afsFetchStatus OutStatus; struct afsToken Token; struct afsVolSync tsync; struct afsFid fid; int vnode, unique, position, length; int code; struct rx_call *tcall; sscanf(&(*argp)[0], "%d", &vnode); ++argp; sscanf(&(*argp)[0], "%d", &unique); ++argp; memset(&fid, 0, sizeof(struct afsFid)); fid.Volume.low = 10; /* XXX */ fid.Vnode = vnode; fid.Unique = unique; sscanf(&(*argp)[0], "%d", &position); ++argp; sscanf(&(*argp)[0], "%d", &length); ++argp; tcall = rx_NewCall(cstruct->conns[0]); code = StartAFS_FetchData(tcall, &fid, &hyp0, position, length, 0); if (!code) { code = FetchProc(tcall); } if (!code) { code = EndAFS_FetchData(tcall, &OutStatus, &Token, &tsync); } code = rx_EndCall(tcall, code); return code; }
static afs_uint32 xf_rxcall_do_write(XFILE * X, void *buf, afs_uint32 count) { struct rxinfo *i = X->refcon; afs_uint32 xcount; xcount = rx_Write(i->call, buf, count); if (xcount == count) return 0; i->code = rx_EndCall(i->call, 0); i->call = 0; return i->code; }
static afs_uint32 xf_rxcall_do_read(XFILE * X, void *buf, afs_uint32 count) { struct rxinfo *i = X->refcon; afs_uint32 xcount; xcount = rx_Read(i->call, buf, count); if (xcount == count) return 0; i->code = rx_EndCall(i->call, 0); i->call = 0; return i->code ? i->code : ERROR_XFILE_RDONLY; }
static afs_uint32 xf_rxcall_do_close(XFILE * X) { struct rxinfo *i = X->refcon; afs_uint32 code; if (i->call) { code = rx_EndCall(i->call, i->code); i->call = 0; } else { code = i->code; } free(i); return code; }
/* ignores all remaining multiRx calls */ void multi_Finalize_Ignore(struct multi_handle *mh) { int i; int nCalls = mh->nConns; for (i = 0; i < nCalls; i++) { struct rx_call *call = mh->calls[i]; if (call) rx_EndCall(call, 0); } #ifdef RX_ENABLE_LOCKS MUTEX_DESTROY(&mh->lock); CV_DESTROY(&mh->cv); #endif /* RX_ENABLE_LOCKS */ osi_Free(mh->calls, sizeof(struct rx_call *) * nCalls); osi_Free(mh->ready, sizeof(short *) * nCalls); osi_Free(mh, sizeof(struct multi_handle)); }
afs_int32 SBOZO_ReBozo(struct rx_call *acall) { afs_int32 code; char caller[MAXKTCNAMELEN]; /* acall is null if called internally to restart bosserver */ if (acall && !afsconf_SuperUser(bozo_confdir, acall, caller)) { code = BZACCESS; goto fail; } if (DoLogging) bozo_Log("%s is executing ReBozo\n", caller); /* start shutdown of all processes */ code = bnode_ApplyInstance(sdproc, NULL); if (code) goto fail; /* wait for all done */ code = bnode_ApplyInstance(swproc, NULL); if (code) goto fail; if (acall) osi_auditU(acall, BOS_RebozoEvent, code, AUD_END); else osi_audit(BOS_RebozoIntEvent, code, AUD_END); if (acall) rx_EndCall(acall, 0); /* try to get it done */ rx_Finalize(); bozo_ReBozo(); /* this reexecs us, and doesn't return, of course */ fail: /* Differentiate between external and internal ReBozo; prevents AFS_Aud_NoCall event */ if (acall) osi_auditU(acall, BOS_RebozoEvent, code, AUD_END); else osi_audit(BOS_RebozoIntEvent, code, AUD_END); return code; /* should only get here in unusual circumstances */ }
afs_int32 Readdir(char **argp) { struct afsFetchStatus OutDirStatus; struct afsVolSync tsync; struct afsFid fid; struct afsToken Token; char *name; struct rx_call *tcall; int vnode, unique, offset, length, NextOffset; int code; sscanf(&(*argp)[0], "%d", &vnode); ++argp; sscanf(&(*argp)[0], "%d", &unique); ++argp; sscanf(&(*argp)[0], "%d", &offset); ++argp; sscanf(&(*argp)[0], "%d", &length); ++argp; memset(&fid, 0, sizeof(struct afsFid)); fid.Volume.low = 10; /* XXX */ fid.Vnode = vnode; fid.Unique = unique; tcall = rx_NewCall(cstruct->conns[0]); code = StartAFS_Readdir(tcall, &fid, offset, length, &hyp0, 0); if (!code) { code = FetchDir(tcall); } if (!code) { code = EndAFS_FetchData(tcall, &NextOffset, &OutDirStatus, &Token, &tsync); } code = rx_EndCall(tcall, code); return (code); }
/* Cannot have static linkage--called from BPrefetch (afs_daemons) */ afs_int32 afs_PrefetchNoCache(struct vcache *avc, afs_ucred_t *acred, struct nocache_read_request *bparms) { struct uio *auio; #ifndef UKERNEL struct iovec *iovecp; #endif struct vrequest *areq; afs_int32 code = 0; struct rx_connection *rxconn; #ifdef AFS_64BIT_CLIENT afs_int32 length_hi, bytes, locked; #endif struct afs_conn *tc; struct rx_call *tcall; struct tlocal1 { struct AFSVolSync tsync; struct AFSFetchStatus OutStatus; struct AFSCallBack CallBack; }; struct tlocal1 *tcallspec; auio = bparms->auio; areq = bparms->areq; #ifndef UKERNEL iovecp = auio->uio_iov; #endif tcallspec = osi_Alloc(sizeof(struct tlocal1)); do { tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK /* ignored */, &rxconn); if (tc) { avc->callback = tc->parent->srvr->server; tcall = rx_NewCall(rxconn); #ifdef AFS_64BIT_CLIENT if (!afs_serverHasNo64Bit(tc)) { code = StartRXAFS_FetchData64(tcall, (struct AFSFid *) &avc->f.fid.Fid, auio->uio_offset, bparms->length); if (code == 0) { COND_GUNLOCK(locked); bytes = rx_Read(tcall, (char *)&length_hi, sizeof(afs_int32)); COND_RE_GLOCK(locked); if (bytes != sizeof(afs_int32)) { length_hi = 0; code = rx_Error(tcall); COND_GUNLOCK(locked); code = rx_EndCall(tcall, code); COND_RE_GLOCK(locked); tcall = NULL; } } } /* afs_serverHasNo64Bit */ if (code == RXGEN_OPCODE || afs_serverHasNo64Bit(tc)) { if (auio->uio_offset > 0x7FFFFFFF) { code = EFBIG; } else { afs_int32 pos; pos = auio->uio_offset; COND_GUNLOCK(locked); if (!tcall) tcall = rx_NewCall(rxconn); code = StartRXAFS_FetchData(tcall, (struct AFSFid *) &avc->f.fid.Fid, pos, bparms->length); COND_RE_GLOCK(locked); } afs_serverSetNo64Bit(tc); } #else code = StartRXAFS_FetchData(tcall, (struct AFSFid *) &avc->f.fid.Fid, auio->uio_offset, bparms->length); #endif if (code == 0) { code = afs_NoCacheFetchProc(tcall, avc, auio, 1 /* release_pages */, bparms->length); } else { afs_warn("BYPASS: StartRXAFS_FetchData failed: %d\n", code); unlock_and_release_pages(auio); goto done; } if (code == 0) { code = EndRXAFS_FetchData(tcall, &tcallspec->OutStatus, &tcallspec->CallBack, &tcallspec->tsync); } else { afs_warn("BYPASS: NoCacheFetchProc failed: %d\n", code); } code = rx_EndCall(tcall, code); } else { afs_warn("BYPASS: No connection.\n"); code = -1; unlock_and_release_pages(auio); goto done; } } while (afs_Analyze(tc, rxconn, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_FETCHDATA, SHARED_LOCK,0)); done: /* * Copy appropriate fields into vcache */ if (!code) afs_ProcessFS(avc, &tcallspec->OutStatus, areq); osi_Free(areq, sizeof(struct vrequest)); osi_Free(tcallspec, sizeof(struct tlocal1)); osi_Free(bparms, sizeof(struct nocache_read_request)); #ifndef UKERNEL /* in UKERNEL, the "pages" are passed in */ osi_Free(iovecp, auio->uio_iovcnt * sizeof(struct iovec)); osi_Free(auio, sizeof(struct uio)); #endif return code; }
static int afs_StoreMini(struct vcache *avc, struct vrequest *areq) { struct afs_conn *tc; struct AFSStoreStatus InStatus; struct AFSFetchStatus OutStatus; struct AFSVolSync tsync; afs_int32 code; struct rx_call *tcall; struct rx_connection *rxconn; afs_size_t tlen, xlen = 0; XSTATS_DECLS; AFS_STATCNT(afs_StoreMini); afs_Trace2(afs_iclSetp, CM_TRACE_STOREMINI, ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, avc->f.m.Length); tlen = avc->f.m.Length; if (avc->f.truncPos < tlen) tlen = avc->f.truncPos; avc->f.truncPos = AFS_NOTRUNC; avc->f.states &= ~CExtendedFile; do { tc = afs_Conn(&avc->f.fid, areq, SHARED_LOCK, &rxconn); if (tc) { #ifdef AFS_64BIT_CLIENT retry: #endif RX_AFS_GUNLOCK(); tcall = rx_NewCall(rxconn); RX_AFS_GLOCK(); /* Set the client mod time since we always want the file * to have the client's mod time and not the server's one * (to avoid problems with make, etc.) It almost always * works fine with standard afs because them server/client * times are in sync and more importantly this storemini * it's a special call that would typically be followed by * the proper store-data or store-status calls. */ InStatus.Mask = AFS_SETMODTIME; InStatus.ClientModTime = avc->f.m.Date; XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREDATA); afs_Trace4(afs_iclSetp, CM_TRACE_STOREDATA64, ICL_TYPE_FID, &avc->f.fid.Fid, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->f.m.Length), ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(xlen), ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(tlen)); RX_AFS_GUNLOCK(); #ifdef AFS_64BIT_CLIENT if (!afs_serverHasNo64Bit(tc)) { code = StartRXAFS_StoreData64(tcall, (struct AFSFid *)&avc->f.fid.Fid, &InStatus, avc->f.m.Length, (afs_size_t) 0, tlen); } else { afs_int32 l1, l2; l1 = avc->f.m.Length; l2 = tlen; if ((avc->f.m.Length > 0x7fffffff) || (tlen > 0x7fffffff) || ((0x7fffffff - tlen) < avc->f.m.Length)) { code = EFBIG; goto error; } code = StartRXAFS_StoreData(tcall, (struct AFSFid *)&avc->f.fid.Fid, &InStatus, l1, 0, l2); } #else /* AFS_64BIT_CLIENT */ code = StartRXAFS_StoreData(tcall, (struct AFSFid *)&avc->f.fid.Fid, &InStatus, avc->f.m.Length, 0, tlen); #endif /* AFS_64BIT_CLIENT */ if (code == 0) { code = EndRXAFS_StoreData(tcall, &OutStatus, &tsync); } #ifdef AFS_64BIT_CLIENT error: #endif code = rx_EndCall(tcall, code); RX_AFS_GLOCK(); XSTATS_END_TIME; #ifdef AFS_64BIT_CLIENT if (code == RXGEN_OPCODE && !afs_serverHasNo64Bit(tc)) { afs_serverSetNo64Bit(tc); goto retry; } #endif /* AFS_64BIT_CLIENT */ } else code = -1; } while (afs_Analyze (tc, rxconn, code, &avc->f.fid, areq, AFS_STATS_FS_RPCIDX_STOREDATA, SHARED_LOCK, NULL)); if (code == 0) afs_ProcessFS(avc, &OutStatus, areq); return code; } /*afs_StoreMini */
/*! * \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 * client_thread( void *vparams) { struct client_data *params = (struct client_data *)vparams; struct rx_call *call; afs_int32 data; int i, j; afs_uint32 *readwrite; int readp = FALSE; afs_uint32 size; afs_uint32 num; for (i = 0; i < params->times; i++) { DBFPRINT(("starting command ")); call = rx_NewCall(params->conn); if (call == NULL) errx(1, "rx_NewCall failed"); data = htonl(RX_PERF_VERSION); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send version (err %d)", rx_Error(call)); data = htonl(params->command); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); data = htonl(rxread_size); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send read size (err %d)", rx_Error(call)); data = htonl(rxwrite_size); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send write read (err %d)", rx_Error(call)); switch (params->command) { case RX_PERF_RECV: DBFPRINT(("command ")); data = htonl(params->bytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); DBFPRINT(("sending(%d) ", params->bytes)); if (do_readbytes(call, params->bytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); if (rx_Read32(call, &data) != 4) errx(1, "failed to read result from server (err %d)", rx_Error(call)); if (data != htonl(RXPERF_MAGIC_COOKIE)) warn("server send wrong magic cookie in responce"); DBFPRINT(("done\n")); break; case RX_PERF_SEND: DBFPRINT(("command ")); data = htonl(params->bytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); DBFPRINT(("sending(%d) ", params->bytes)); if (do_sendbytes(call, params->bytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); if (rx_Read32(call, &data) != 4) errx(1, "failed to read result from server (err %d)", rx_Error(call)); if (data != htonl(RXPERF_MAGIC_COOKIE)) warn("server send wrong magic cookie in responce"); DBFPRINT(("done\n")); break; case RX_PERF_RPC: DBFPRINT(("commands ")); data = htonl(params->sendbytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); data = htonl(params->readbytes); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send command (err %d)", rx_Error(call)); DBFPRINT(("send(%d) ", params->sendbytes)); if (do_sendbytes(call, params->sendbytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); DBFPRINT(("recv(%d) ", params->readbytes)); if (do_readbytes(call, params->readbytes)) errx(1, "sendbytes (err %d)", rx_Error(call)); if (rx_Read32(call, &data) != 4) errx(1, "failed to read result from server (err %d)", rx_Error(call)); if (data != htonl(RXPERF_MAGIC_COOKIE)) warn("server send wrong magic cookie in responce"); DBFPRINT(("done\n")); break; case RX_PERF_FILE: readfile(params->filename, &readwrite, &num); data = htonl(num); if (rx_Write32(call, &data) != 4) errx(1, "rx_Write failed to send size (err %d)", rx_Error(call)); if (rx_Write(call, (char *)readwrite, num * sizeof(afs_uint32)) != num * sizeof(afs_uint32)) errx(1, "rx_Write failed to send list (err %d)", rx_Error(call)); for (j = 0; j < num; j++) { if (readwrite[j] == 0) readp = !readp; size = ntohl(readwrite[j]) * sizeof(afs_uint32); if (readp) { if (do_readbytes(call, size)) errx(1, "sendbytes (err %d)", rx_Error(call)); DBFPRINT(("read\n")); } else { if (do_sendbytes(call, size)) errx(1, "sendbytes (err %d)", rx_Error(call)); DBFPRINT(("send\n")); } } break; default: abort(); } rx_EndCall(call, 0); } #ifdef AFS_PTHREAD_ENV pthread_exit(NULL); #endif return NULL; }
/* this is not yet 64-bit clean */ ssize_t afscp_PRead(const struct afscp_venusfid * fid, void *buffer, size_t count, off_t offset) { struct AFSFetchStatus fst; struct AFSVolSync vs; struct AFSCallBack cb; struct AFSFid tf = fid->fid; struct afscp_volume *vol; struct afscp_server *server; struct rx_call *c = NULL; int code, code2 = 0; int i, j, bytes, totalbytes = 0; int bytesremaining; char *p; time_t now; vol = afscp_VolumeById(fid->cell, fid->fid.Volume); if (vol == NULL) { afscp_errno = ENOENT; return -1; } code = ENOENT; for (i = 0; i < vol->nservers; i++) { server = afscp_ServerByIndex(vol->servers[i]); if (server && server->naddrs > 0) { for (j = 0; j < server->naddrs; j++) { c = rx_NewCall(server->conns[j]); if (c != 0) { p = buffer; code = StartRXAFS_FetchData(c, &tf, offset, count); if (code != 0) { code = rx_EndCall(c, code); continue; } bytes = rx_Read(c, (char *)&bytesremaining, sizeof(afs_int32)); if (bytes != sizeof(afs_int32)) { code = rx_EndCall(c, bytes); continue; } bytesremaining = ntohl(bytesremaining); totalbytes = 0; while (bytesremaining > 0) { bytes = rx_Read(c, p, bytesremaining); if (bytes <= 0) break; p += bytes; totalbytes += bytes; bytesremaining -= bytes; } if (bytesremaining == 0) { time(&now); code2 = EndRXAFS_FetchData(c, &fst, &cb, &vs); if (code2 == 0) afscp_AddCallBack(server, &fid->fid, &fst, &cb, now); } code = rx_EndCall(c, code2); } if (code == 0) { return totalbytes; } } } } afscp_errno = code; return -1; }
/* this is not yet 64-bit clean */ ssize_t afscp_PWrite(const struct afscp_venusfid * fid, const void *buffer, size_t count, off_t offset) { struct AFSFetchStatus fst; struct AFSStoreStatus sst; struct AFSVolSync vs; struct AFSCallBack cb; struct AFSFid tf = fid->fid; struct afscp_volume *vol; struct afscp_server *server; struct rx_call *c = NULL; int code, code2 = 0; int i, j, bytes, totalbytes = 0; int bytesremaining; const char *p; off_t filesize; time_t now; vol = afscp_VolumeById(fid->cell, fid->fid.Volume); if (vol == NULL) { afscp_errno = ENOENT; return -1; } if (vol->voltype != RWVOL) { afscp_errno = EROFS; return -1; } code = ENOENT; for (i = 0; i < vol->nservers; i++) { server = afscp_ServerByIndex(vol->servers[i]); if (server && server->naddrs > 0) { for (j = 0; j < server->naddrs; j++) { code = RXAFS_FetchStatus(server->conns[j], &tf, &fst, &cb, &vs); if (code != 0) continue; sst.Mask = AFS_SETMODTIME; time(&now); sst.ClientModTime = now; filesize = fst.Length; if (offset + count > filesize) filesize = offset + count; c = rx_NewCall(server->conns[j]); if (c != 0) { p = buffer; code = StartRXAFS_StoreData(c, &tf, &sst, offset, count, filesize); if (code != 0) { code = rx_EndCall(c, code); continue; } /* * seems to write file length to beginning of file -- why? */ /* * bytesremaining = htonl(count); * bytes = rx_Write(c, (char *)&bytesremaining, * sizeof(afs_int32)); * if (bytes != sizeof(afs_int32)) { * code = rx_EndCall(c, bytes); * continue; * } */ bytesremaining = count; totalbytes = 0; while (bytesremaining > 0) { bytes = rx_Write(c, (char *)p, bytesremaining); if (bytes <= 0) break; p += bytes; totalbytes += bytes; bytesremaining -= bytes; } if (bytesremaining == 0) { code2 = EndRXAFS_StoreData(c, &fst, &vs); } code = rx_EndCall(c, code2); } if (code == 0) { return totalbytes; } } } } afscp_errno = code; return -1; }
int main(int argc, char **argv) { char scell[MAXCELLCHARS], dcell[MAXCELLCHARS]; afs_uint32 ssrv, dsrv; char *databuffer, *srcf = NULL, *destd = NULL, *destf = NULL, *destpath = NULL; struct stat statbuf; struct AFSStoreStatus sst; struct AFSFetchStatus fst, dfst; struct AFSVolSync vs; struct AFSCallBack scb, dcb; struct AFSFid sf, dd, df; int filesz = 0; int ch, blksize, bytesremaining, bytes; struct timeval start, finish; struct timezone tz; struct rx_securityClass *ssc = 0, *dsc = 0; int sscindex, dscindex; struct rx_connection *sconn = NULL, *dconn = NULL; struct rx_call *scall = NULL, *dcall = NULL; int code = 0, fetchcode, storecode, printcallerrs = 0; int slcl = 0, dlcl = 0, unlock = 0; int sfd = 0, dfd = 0, unauth = 0; struct AFSCBFids theFids; struct AFSCBs theCBs; blksize = 8 * 1024; while ((ch = getopt(argc, argv, "iouUb:")) != -1) { switch (ch) { case 'b': blksize = atoi(optarg); break; case 'i': slcl = 1; break; case 'o': dlcl = 1; break; case 'u': unauth = 1; break; case 'U': unlock = 1; break; default: printf("Unknown option '%c'\n", ch); exit(1); } } if (argc - optind + unlock < 2) { fprintf(stderr, "Usage: afscp [-i|-o]] [-b xfersz] [-u] [-U] source [dest]\n"); fprintf(stderr, " -b Set block size\n"); fprintf(stderr, " -i Source is local (copy into AFS)\n"); fprintf(stderr, " -o Dest is local (copy out of AFS)\n"); fprintf(stderr, " -u Run unauthenticated\n"); fprintf(stderr, " -U Send an unlock request for source. (dest path not required)\n"); fprintf(stderr, "source and dest can be paths or specified as:\n"); fprintf(stderr, " @afs:cellname:servername:volume:vnode:uniq\n"); exit(1); } srcf = argv[optind++]; if (!unlock) { destpath = argv[optind++]; destd = strdup(destpath); if (!destd) { perror("strdup"); exit(1); } if ((destf = strrchr(destd, '/'))) { *destf++ = 0; } else { destf = destd; destd = "."; } } else if (slcl) { fprintf(stderr, "-i and -U cannot be used together\n"); } if (!slcl && statfile(srcf, scell, &ssrv, &sf)) { fprintf(stderr, "Cannot get attributes of %s\n", srcf); exit(1); } if (!unlock && !dlcl && statfile(destd, dcell, &dsrv, &dd)) { fprintf(stderr, "Cannot get attributes of %s\n", destd); exit(1); } if ((databuffer = malloc(blksize)) == NULL) { perror("malloc"); exit(1); } if (do_rx_Init()) exit(1); if (start_cb_server()) { printf("Cannot start callback service\n"); goto Fail_rx; } if (!slcl) { sscindex = scindex_RXKAD; if (unauth || (ssc = get_sc(scell)) == NULL) { ssc = rxnull_NewClientSecurityObject(); sscindex = scindex_NULL; /*printf("Cannot get authentication for cell %s; running unauthenticated\n", scell); */ } sscindex = scindex_NULL; if ((sconn = rx_NewConnection(ssrv, htons(AFSCONF_FILEPORT), 1, ssc, sscindex)) == NULL) { struct in_addr s; s.s_addr = ssrv; printf("Cannot initialize rx connection to source server (%s)\n", inet_ntoa(s)); goto Fail_sc; } } if (!dlcl && !unlock) { if (!slcl && ssrv == dsrv) { dconn = sconn; dsc = NULL; } else { if (slcl || strcmp(scell, dcell)) { dscindex = scindex_RXKAD; if (unauth || (dsc = get_sc(dcell)) == NULL) { dsc = rxnull_NewClientSecurityObject(); dscindex = scindex_NULL; /*printf("Cannot get authentication for cell %s; running unauthenticated\n", dcell); */ } dscindex = scindex_NULL; } else { dsc = ssc; dscindex = sscindex; } if ((dconn = rx_NewConnection(dsrv, htons(AFSCONF_FILEPORT), 1, dsc, dscindex)) == NULL) { struct in_addr s; s.s_addr = dsrv; printf ("Cannot initialize rx connection to dest server (%s)\n", inet_ntoa(s)); goto Fail_sconn; } } } memset(&sst, 0, sizeof(struct AFSStoreStatus)); if (dlcl && !unlock) { dfd = open(destpath, O_RDWR | O_CREAT | O_EXCL, 0666); if (dfd < 0 && errno == EEXIST) { printf("%s already exists, overwriting\n", destpath); dfd = open(destpath, O_RDWR | O_TRUNC, 0666); if (dfd < 0) { fprintf(stderr, "Cannot open %s (%s)\n", destpath, afs_error_message(errno)); goto Fail_dconn; } } else if (dfd < 0) { fprintf(stderr, "Cannot open %s (%s)\n", destpath, afs_error_message(errno)); goto Fail_dconn; } } else if (!unlock) { if ((code = RXAFS_CreateFile(dconn, &dd, destf, &sst, &df, &fst, &dfst, &dcb, &vs))) { if (code == EEXIST) { printf("%s already exits, overwriting\n", destpath); if (statfile(destpath, dcell, &dsrv, &df)) fprintf(stderr, "Cannot get attributes of %s\n", destpath); else code = 0; } else { printf("Cannot create %s (%s)\n", destpath, afs_error_message(code)); if (code) goto Fail_dconn; } } } if (slcl) { sfd = open(srcf, O_RDONLY, 0); if (sfd < 0) { fprintf(stderr, "Cannot open %s (%s)\n", srcf, afs_error_message(errno)); goto Fail_dconn; } if (fstat(sfd, &statbuf) < 0) { fprintf(stderr, "Cannot stat %s (%s)\n", srcf, afs_error_message(errno)); close(sfd); goto Fail_dconn; } } else { if ((code = RXAFS_FetchStatus(sconn, &sf, &fst, &scb, &vs))) { printf("Cannot fetchstatus of %d.%d (%s)\n", sf.Volume, sf.Vnode, afs_error_message(code)); goto Fail_dconn; } } if (slcl) { filesz = statbuf.st_size; } else { filesz = fst.Length; } printcallerrs = 0; fetchcode = 0; storecode = 0; if (!slcl && !unlock) scall = rx_NewCall(sconn); if (!dlcl && !unlock) dcall = rx_NewCall(dconn); gettimeofday(&start, &tz); if (unlock) { if (fst.lockCount) { printf("Sending 1 unlock for %s (%d locks)\n", srcf, fst.lockCount); if ((code = RXAFS_ReleaseLock(sconn, &sf, &vs))) { printf("Unable to unlock %s (%s)\n", srcf, afs_error_message(code)); } } else { printf("No locks for %s\n", srcf); } fetchcode = code; goto Finish; } if (!slcl) { if ((code = StartRXAFS_FetchData(scall, &sf, 0, filesz))) { printf("Unable to fetch data from %s (%s)\n", srcf, afs_error_message(code)); goto Fail_call; } } if (!dlcl) { if (slcl) { sst.Mask = AFS_SETMODTIME | AFS_SETMODE; sst.ClientModTime = statbuf.st_mtime; sst.UnixModeBits = statbuf.st_mode & ~(S_IFMT | S_ISUID | S_ISGID); } else { sst.Mask = AFS_SETMODTIME | AFS_SETMODE; sst.ClientModTime = fst.ClientModTime; sst.UnixModeBits = fst.UnixModeBits & ~(S_IFMT | S_ISUID | S_ISGID); } if ((code = StartRXAFS_StoreData(dcall, &df, &sst, 0, filesz, filesz))) { printf("Unable to store data to %s (%s)\n", destpath, afs_error_message(code)); goto Fail_call; } } if (slcl) { bytesremaining = statbuf.st_size; } else { rx_Read(scall, (char *)&bytesremaining, sizeof(afs_int32)); bytesremaining = ntohl(bytesremaining); } while (bytesremaining > 0) { /*printf("%d bytes remaining\n",bytesremaining); */ if (slcl) { if ((bytes = read(sfd, databuffer, min(blksize, bytesremaining))) <= 0) { fetchcode = errno; break; } } else { if ((bytes = rx_Read(scall, databuffer, min(blksize, bytesremaining))) <= 0) break; } if (dlcl) { if (write(dfd, databuffer, bytes) != bytes) { storecode = errno; break; } } else { if (rx_Write(dcall, databuffer, bytes) != bytes) break; } bytesremaining -= bytes; /*printf("%d bytes copied\n",bytes); */ } if (bytesremaining > 0) { printf("Some network error occured while copying data\n"); goto Fail_call; } if (!slcl) fetchcode = EndRXAFS_FetchData(scall, &fst, &scb, &vs); if (!dlcl) storecode = EndRXAFS_StoreData(dcall, &fst, &vs); printcallerrs = 1; Fail_call: if (slcl) { if (close(sfd) && !fetchcode) fetchcode = errno; } else { fetchcode = rx_EndCall(scall, fetchcode); } if (fetchcode && printcallerrs) printf("Error returned from fetch: %s\n", afs_error_message(fetchcode)); if (dlcl) { if (close(dfd) && !storecode) storecode = errno; } else if (!unlock) { storecode = rx_EndCall(dcall, storecode); } if (storecode && printcallerrs) printf("Error returned from store: %s\n", afs_error_message(storecode)); Finish: gettimeofday(&finish, &tz); if (!slcl) { theFids.AFSCBFids_len = 1; theFids.AFSCBFids_val = &sf; theCBs.AFSCBs_len = 1; theCBs.AFSCBs_val = &scb; scb.CallBackType = CB_DROPPED; if ((code = RXAFS_GiveUpCallBacks(sconn, &theFids, &theCBs))) printf("Could not give up source callback: %s\n", afs_error_message(code)); } if (!dlcl) { theFids.AFSCBFids_len = 1; theFids.AFSCBFids_val = &df; theCBs.AFSCBs_len = 1; theCBs.AFSCBs_val = &dcb; dcb.CallBackType = CB_DROPPED; if ((code = RXAFS_GiveUpCallBacks(dconn, &theFids, &theCBs))) printf("Could not give up target callback: %s\n", afs_error_message(code)); } if (code == 0) code = storecode; if (code == 0) code = fetchcode; Fail_dconn: if (!dlcl && !unlock && (slcl || dconn != sconn)) rx_DestroyConnection(dconn); Fail_sconn: if (!slcl) rx_DestroyConnection(sconn); Fail_sc: if (dsc && dsc != ssc) RXS_Close(dsc); if (ssc) RXS_Close(ssc); Fail_rx: rx_Finalize(); free(databuffer); if (printcallerrs && !unlock) { double rate, size, time; if (finish.tv_sec == start.tv_sec) { printf("Copied %d bytes in %d microseconds\n", filesz, (int)(finish.tv_usec - start.tv_usec)); } else { printf("Copied %d bytes in %d seconds\n", filesz, (int)(finish.tv_sec - start.tv_sec)); } size = filesz / 1024.0; time = finish.tv_sec - start.tv_sec + (finish.tv_usec - start.tv_usec) / 1e+06; rate = size / time; printf("Transfer rate %g Kbytes/sec\n", rate); } exit(code != 0); }
afs_int32 StoreData(char **argp) { struct afsStoreStatus InStatus; struct afsFetchStatus OutStatus; struct afsVolSync tsync; struct afsFid fid; int vnode, unique, position, length, filelength; int mode, owner, len; int code; char *string; struct rx_call *tcall; sscanf(&(*argp)[0], "%d", &vnode); ++argp; sscanf(&(*argp)[0], "%d", &unique); ++argp; memset(&fid, 0, sizeof(struct afsFid)); fid.Volume.low = 10; /* XXX */ fid.Vnode = vnode; fid.Unique = unique; sscanf(&(*argp)[0], "%d", &position); ++argp; sscanf(&(*argp)[0], "%d", &length); ++argp; sscanf(&(*argp)[0], "%d", &filelength); ++argp; memset(&InStatus, 0, sizeof(struct afsStoreStatus)); sscanf(&(*argp)[0], "%d", &mode); ++argp; sscanf(&(*argp)[0], "%d", &owner); ++argp; sscanf(&(*argp)[0], "%d", &len); ++argp; if (mode != -1) { InStatus.mode = mode; InStatus.mask |= AFS_SETMODE; } if (owner != -1) { InStatus.owner = owner; InStatus.mask |= AFS_SETOWNER; } if (length != -1) { InStatus.length = length; InStatus.mask |= AFS_SETLENGTH; } string = &argp[0][0]; ++argp; tcall = rx_NewCall(cstruct->conns[0]); code = StartAFS_StoreData(tcall, &fid, &InStatus, position, length, filelength, &hyp0, 0); if (!code) { code = StoreProc(tcall, string, length); } if (!code) { code = EndAFS_StoreData(tcall, &OutStatus, &tsync); } code = rx_EndCall(tcall, code); return (code); }
static long Copious(struct client *c, char *buf, u_long buflen) { long code; struct rx_call *call; long i; long inlen = c->sendLen; long outlen = c->recvLen; long d = 23; long mysum; size_t outsum; mysum = 0; for (i = 0; i < inlen; i++) mysum += (d++ & 0xff); call = rx_NewCall(c->conn); code = StartRXKST_Copious(call, inlen, mysum, outlen); if (code == 0) { long tlen; long xfer = 0; long n; d = 23; while (xfer < inlen) { tlen = inlen - xfer; if (tlen > buflen) tlen = buflen; for (i = 0; i < tlen; i++) buf[i] = (d++ & 0xff); n = rx_Write(call, buf, tlen); if (n != tlen) { if (n < 0) code = n; else code = RXKST_WRITESHORT; break; } xfer += tlen; } if (code == 0) { xfer = 0; mysum = 0; while (xfer < outlen) { tlen = outlen - xfer; if (tlen > buflen) tlen = buflen; n = rx_Read(call, buf, tlen); if (n != tlen) { if (n < 0) code = n; else code = RXKST_READSHORT; break; } for (i = 0; i < tlen; i++) mysum += buf[i]; xfer += tlen; } } } if (code == 0) code = EndRXKST_Copious(call, &outsum); code = rx_EndCall(call, code); if (code) return code; if (outsum != mysum) { return RXKST_BADOUTPUTSUM; } return 0; }
int SendFile(char *file, struct rx_connection *conn) { struct rx_call *call; int fd; struct stat status; int blockSize, bytesLeft; char *buf; int nbytes; int err; struct clock startTime; int receivedStore = 0; struct clock totalReadvDelay; int nReadvs; int code; #ifdef AFS_AIX_ENV #include <sys/statfs.h> struct statfs tstatfs; #endif if (timeReadvs) { nReadvs = 0; clock_Zero(&totalReadvDelay); } fd = open(file, O_RDONLY, 0); if (fd < 0) Abort("Couldn't open %s\n", file); fstat(fd, &status); #ifdef AFS_NT40_ENV blockSize = 1024; #else #ifdef AFS_AIX_ENV /* Unfortunately in AIX valuable fields such as st_blksize are gone from the stat structure!! */ fstatfs(fd, &tstatfs); blockSize = tstatfs.f_bsize; #else blockSize = status.st_blksize; #endif #endif buf = (char *)osi_Alloc(blockSize); bytesLeft = status.st_size; clock_GetTime(&startTime); call = rx_NewCall(conn); while (bytesLeft) { if (!receivedStore && rx_GetRemoteStatus(call) == 79) { receivedStore = 1; fprintf(stderr, "Remote status indicates file accepted (\"received store\")\n"); } nbytes = (bytesLeft > blockSize ? blockSize : bytesLeft); errno = 0; code = read(fd, buf, nbytes); if (code != nbytes) { Abort("Only read %d bytes of %d, errno=%d\n", code, nbytes, errno); } code = rx_Write(call, buf, nbytes); if (code != nbytes) { Abort("Only wrote %d bytes of %d\n", code, nbytes); } bytesLeft -= nbytes; } while ((nbytes = rx_Read(call, buf, sizeof(buf))) > 0) { char *p = buf; while (nbytes--) { putchar(*p); p++; } } if ((err = rx_EndCall(call, 0)) != 0) { fprintf(stderr, "rx_Endcall returned error %d\n", err); } else { struct clock totalTime; float elapsedTime; clock_GetTime(&totalTime); clock_Sub(&totalTime, &startTime); elapsedTime = totalTime.sec + totalTime.usec / 1e6; fprintf(stderr, "Sent %d bytes in %0.3f seconds: %0.0f bytes per second\n", (int) status.st_size, elapsedTime, status.st_size / elapsedTime); if (timeReadvs) { float delay = clock_Float(&totalReadvDelay) / nReadvs; fprintf(stderr, "%d readvs, average delay of %0.4f seconds\n", nReadvs, delay); } } close(fd); return(0); }
int main(int argc, char **argv) { char *hostname; struct hostent *hostent; afs_uint32 host; int logstdout = 0; struct rx_connection *conn; struct rx_call *call; struct rx_peer *peer; int err = 0; int nCalls = 1, nBytes = 1; int bufferSize = 4000000; char *buffer; char *sendFile = 0; int setFD = 0; int jumbo = 0; #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) setlinebuf(stdout); rxi_syscallp = test_syscall; #endif argv++; argc--; while (argc && **argv == '-') { if (strcmp(*argv, "-silent") == 0) print = 0; if (strcmp(*argv, "-jumbo") == 0) jumbo = 1; else if (strcmp(*argv, "-nc") == 0) nCalls = atoi(*++argv), argc--; else if (strcmp(*argv, "-nb") == 0) nBytes = atoi(*++argv), argc--; else if (strcmp(*argv, "-np") == 0) rx_nPackets = atoi(*++argv), argc--; else if (!strcmp(*argv, "-nsf")) rxi_nSendFrags = atoi(*++argv), argc--; else if (!strcmp(*argv, "-nrf")) rxi_nRecvFrags = atoi(*++argv), argc--; else if (strcmp(*argv, "-twind") == 0) rx_initSendWindow = atoi(*++argv), argc--; else if (strcmp(*argv, "-rwind") == 0) rx_initReceiveWindow = atoi(*++argv), argc--; else if (strcmp(*argv, "-rxlog") == 0) rxlog = 1; else if (strcmp(*argv, "-logstdout") == 0) logstdout = 1; else if (strcmp(*argv, "-eventlog") == 0) eventlog = 1; else if (strcmp(*argv, "-drop") == 0) { #ifdef RXDEBUG rx_intentionallyDroppedPacketsPer100 = atoi(*++argv), argc--; #else fprintf(stderr, "ERROR: Compiled without RXDEBUG\n"); #endif } else if (strcmp(*argv, "-burst") == 0) { burst = atoi(*++argv), argc--; burstTime.sec = atoi(*++argv), argc--; burstTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-retry") == 0) { retryTime.sec = atoi(*++argv), argc--; retryTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-timeout") == 0) timeout = atoi(*++argv), argc--; else if (strcmp(*argv, "-fill") == 0) fillPackets++; else if (strcmp(*argv, "-file") == 0) sendFile = *++argv, argc--; else if (strcmp(*argv, "-timereadvs") == 0) timeReadvs = 1; else if (strcmp(*argv, "-wait") == 0) { /* Wait time between calls--to test lastack code */ waitTime.sec = atoi(*++argv), argc--; waitTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-compute") == 0) { /* Simulated "compute" time for each call--to test acknowledgement protocol. This is simulated by doing an iomgr_select: imperfect, admittedly. */ computeTime.sec = atoi(*++argv), argc--; computeTime.usec = atoi(*++argv), argc--; } else if (strcmp(*argv, "-fd") == 0) { /* Open at least this many fd's. */ setFD = atoi(*++argv), argc--; } else { err = 1; break; } argv++, argc--; } if (err || argc != 1) Quit("usage: rx_ctest [-silent] [-rxlog] [-eventlog] [-nc NCALLS] [-np NPACKETS] hostname"); hostname = *argv++, argc--; if (rxlog || eventlog) { if (logstdout) debugFile = stdout; else debugFile = fopen("rx_ctest.db", "w"); if (debugFile == NULL) Quit("Couldn't open rx_ctest.db"); if (rxlog) rx_debugFile = debugFile; if (eventlog) rxevent_debugFile = debugFile; } signal(SIGINT, intSignal); /*Changed to sigquit since dbx is broken right now */ #ifndef AFS_NT40_ENV signal(SIGQUIT, quitSignal); #endif #ifdef AFS_NT40_ENV if (afs_winsockInit() < 0) { printf("Can't initialize winsock.\n"); exit(1); } rx_EnableHotThread(); #endif rx_SetUdpBufSize(256 * 1024); if (!jumbo) rx_SetNoJumbo(); hostent = gethostbyname(hostname); if (!hostent) Abort("host %s not found", hostname); if (hostent->h_length != 4) Abort("host address is disagreeable length (%d)", hostent->h_length); memcpy((char *)&host, hostent->h_addr, sizeof(host)); if (setFD > 0) OpenFD(setFD); if (rx_Init(0) != 0) { printf("RX failed to initialize, exiting.\n"); exit(2); } if (setFD > 0) { printf("rx_socket=%d\n", rx_socket); } printf("Using %d packet buffers\n", rx_nPackets); conn = rx_NewConnection(host, htons(2500), 3, rxnull_NewClientSecurityObject(), 0); if (!conn) Abort("unable to make a new connection"); /* Set initial parameters. This is (currently) not the approved interface */ peer = rx_PeerOf(conn); if (burst) peer->burstSize = peer->burst = burst; if (!clock_IsZero(&burstTime)) peer->burstWait = burstTime; if (!clock_IsZero(&retryTime)) peer->rtt = _8THMSEC(&retryTime); if (sendFile) SendFile(sendFile, conn); else { buffer = (char *)osi_Alloc(bufferSize); while (nCalls--) { struct clock startTime; struct timeval t; int nbytes; int nSent; int bytesSent = 0; int bytesRead = 0; call = rx_NewCall(conn); if (!call) Abort("unable to make a new call"); clock_GetTime(&startTime); for (bytesSent = 0; bytesSent < nBytes; bytesSent += nSent) { int tryCount; tryCount = (bufferSize > nBytes - bytesSent) ? nBytes - bytesSent : bufferSize; nSent = rx_Write(call, buffer, tryCount); if (nSent == 0) break; } for (bytesRead = 0; (nbytes = rx_Read(call, buffer, bufferSize)); bytesRead += nbytes) { }; if (print) printf("Received %d characters in response\n", bytesRead); err = rx_EndCall(call, 0); if (err) printf("Error %d returned from rpc call\n", err); else { struct clock totalTime; float elapsedTime; clock_GetTime(&totalTime); clock_Sub(&totalTime, &startTime); elapsedTime = clock_Float(&totalTime); fprintf(stderr, "Sent %d bytes in %0.3f seconds: %0.0f bytes per second\n", bytesSent, elapsedTime, bytesSent / elapsedTime); } if (!clock_IsZero(&computeTime)) { t.tv_sec = computeTime.sec; t.tv_usec = computeTime.usec; if (select(0, 0, 0, 0, &t) != 0) Quit("Select didn't return 0"); } if (!clock_IsZero(&waitTime)) { struct timeval t; t.tv_sec = waitTime.sec; t.tv_usec = waitTime.usec; #ifdef AFS_PTHREAD_ENV select(0, 0, 0, 0, &t); #else IOMGR_Sleep(t.tv_sec); #endif } if (debugFile) rx_PrintPeerStats(debugFile, rx_PeerOf(conn)); rx_PrintPeerStats(stdout, rx_PeerOf(conn)); } } Quit("testclient: done!\n"); return 0; }