/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
+#include <roken.h>
-#include <sys/types.h>
-#ifdef AFS_NT40_ENV
-#include <winsock2.h>
-#else
-#include <sys/time.h>
-#include <sys/file.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#endif
-#include <stdlib.h>
#include <rx/xdr.h>
#include <rx/rx.h>
#include <lwp.h>
#include <lock.h>
-#include <errno.h>
#include <afs/tcdata.h>
#include <afs/bubasics.h>
#include <afs/budb_client.h>
+#include <afs/butm_prototypes.h>
#include <afs/vldbint.h>
#include <afs/ktime.h>
#include <afs/vlserver.h>
+#include <afs/afsint.h>
#include <afs/volser.h>
+#include <afs/volser_prototypes.h>
#include <afs/volint.h>
#include <afs/cellconfig.h>
+#include <afs/bucoord_prototypes.h>
+#include "butc_internal.h"
#include "error_macros.h"
#include "butc_xbsa.h"
#include "afs/butx.h"
-
/* GLOBAL CONFIGURATION PARAMETERS */
extern int dump_namecheck;
extern int queryoperator;
dlqlinkT savedEntries;
dlqlinkT entries_to_flush;
-afs_int32 flushSavedEntries(), finishDump(), finishTape(), useTape(),
-addVolume();
-
-extern struct rx_connection *UV_Bind();
-
extern afs_int32 groupId;
extern afs_int32 BufferSize;
extern afs_int32 statusSize;
* 6) Ensure bucoord status calls work
*
* notes
- * pass 3:
+ * pass 3:
* keep token timeout. If no user reponse (idle time > some period)
* and tokens about to time out, terminate dump. This provides at
* least something usable.
else \
sprintf(dumpname, "%s (DumpId %u)", name, dbDumpId);
-#if defined(AFS_NT40_ENV) || (defined(AFS_DARWIN_ENV) && !defined(AFS_DARWIN60_ENV)) || defined(AFS_SUN4_ENV)
-int
-localtime_r(time_t * t, struct tm *tm)
-{
- memcpy(tm, localtime(t), sizeof(struct tm));
- return 0;
-}
-#endif
-
struct dumpRock {
/* status only */
int tapeSeq;
struct dumpNode *node;
};
+/* Forward declarations */
+
+int makeVolumeHeader(struct volumeHeader *, struct dumpRock *, int);
+int volumeHeader_hton(struct volumeHeader *, struct volumeHeader *);
+char retryPrompt(char *, afs_int32, afs_uint32);
+int getDumpTape(struct dumpRock *, int, afs_int32);
+int getXBSATape(struct dumpRock *);
+afs_int32 createDump(struct dumpRock *);
+
/* configuration variables */
#define HITEOT(code) ((code == BUTM_IO) || (code == BUTM_EOT) || (code == BUTM_IOCTL))
extern int autoQuery;
calcExpirationDate(afs_int32 expType, afs_int32 expDate, afs_int32 createTime)
{
struct ktime_date kd;
- afs_int32 Add_RelDate_to_Time();
switch (expType) {
case BC_REL_EXPDATE:
*/
Int32To_ktimeRelDate(expDate, &kd);
return (Add_RelDate_to_Time(&kd, createTime));
- break;
case BC_ABS_EXPDATE:
return (expDate);
- break;
case BC_NO_EXPDATE:
default:
}
}
-afs_int32 curr_bserver = 0;
+afs_uint32 curr_bserver = 0;
struct rx_connection *curr_fromconn = (struct rx_connection *)0;
struct rx_connection *
-Bind(afs_int32 server)
+Bind(afs_uint32 server)
{
if (curr_fromconn) {
if (curr_bserver == server) /* Keep connection if have it */
/* notes
* 1) save the chunksize or otherwise ensure tape space remaining is
* check frequently enough
- * 2) This is called once. For partial dumps, need to
+ * 2) This is called once. For partial dumps, need to
* ensure that the tape device is left in the correct state for
* further dumps.
- *
+ *
*/
#define BIGCHUNK 102400
buffer = bufferBlock + BUTM_HDRSIZE;
/* Dump one volume fragment at a time until we dump the full volume.
- * A volume with more than 1 fragment means the volume will 'span'
+ * A volume with more than 1 fragment means the volume will 'span'
* 2 or more tapes.
*/
for (fragmentNumber = 1; !endofvolume; fragmentNumber++) { /*frag */
/* Create and Write the volume header */
makeVolumeHeader(&hostVolumeHeader, dparamsPtr, fragmentNumber);
hostVolumeHeader.contd = ((fragmentNumber == 1) ? 0 : TC_VOLCONTD);
- volumeHeader_hton(&hostVolumeHeader, buffer);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)buffer);
rc = butm_WriteFileData(tapeInfoPtr, buffer, 1,
sizeof(hostVolumeHeader));
chunkSize = 0;
fragmentvolume = 0;
while (!endofvolume && !fragmentvolume) { /*w */
- bytesread = 0;
-
/* Check for abort in the middle of writing data */
if (volBytesRead >= chunkSize) {
chunkSize += BIGCHUNK;
/* Determine how much data to read in upcoming RX_Read() call */
toread = dataSize;
/* Check if we are close to the EOT. There should at least be some
- * data on the tape before it is switched. HACK: we have to split a
- * volume across tapes because the volume trailer says the dump
- * continues on the next tape (and not the filemark). This could
- * result in a volume starting on one tape (no volume data dumped) and
- * continued on the next tape. It'll work, just requires restore to
+ * data on the tape before it is switched. HACK: we have to split a
+ * volume across tapes because the volume trailer says the dump
+ * continues on the next tape (and not the filemark). This could
+ * result in a volume starting on one tape (no volume data dumped) and
+ * continued on the next tape. It'll work, just requires restore to
* switch tapes. This allows many small volumes (<16K) to be dumped.
*/
kRemaining = butm_remainingKSpace(tapeInfoPtr);
}
}
+#ifdef xbsa
+ /* Set aside space for the trailing volume header when using large buffers. */
+ if (XBSAMAXBUFFER < toread + sizeof(hostVolumeHeader)) {
+ toread = XBSAMAXBUFFER - sizeof(hostVolumeHeader);
+ }
+#endif
+
/* Read some volume data. */
if (fragmentvolume) {
bytesread = 0;
hostVolumeHeader.contd = (endofvolume ? 0 : TC_VOLCONTD);
hostVolumeHeader.magic = TC_VOLENDMAGIC;
hostVolumeHeader.endTime = (endofvolume ? time(0) : 0);
- volumeHeader_hton(&hostVolumeHeader, &buffer[bytesread]);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)&buffer[bytesread]);
bytesread += sizeof(hostVolumeHeader);
}
dparamsPtr->curVolumeStatus = DUMP_SUCCESS;
error_exit:
- /*
+ /*
* If we hit the end, see if this is the first volume on the tape or not.
* Also, mark the tape as finished if the tape contains other dumps.
*/
}
}
- /*
+ /*
* This is used when an error occurs part way into a volume dump. Clean
* the tape state by writing an FileEnd mark. Forgo this action if we hit
* the end of tape.
/* Create and Write the volume header */
makeVolumeHeader(&hostVolumeHeader, dparamsPtr, 1);
hostVolumeHeader.contd = 0;
- volumeHeader_hton(&hostVolumeHeader, buffer);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)buffer);
- rc = xbsa_WriteObjectData(&butxInfo, buffer, sizeof(struct volumeHeader),
- &bytesWritten);
+ rc = xbsa_WriteObjectData(&butxInfo, buffer,
+ sizeof(struct volumeHeader), &bytesWritten);
if (rc != XBSA_SUCCESS) {
ErrorLog(1, taskId, rc, 0,
"Unable to write VolumeHeader data to the server\n");
bytesWritten = sizeof(struct volumeHeader);
if (bytesWritten != sizeof(struct volumeHeader)) {
ErrorLog(1, taskId, rc, 0,
- "The size of VolumeHeader written (%d) does not equal its actual size (%d)\n",
+ "The size of VolumeHeader written (%d) does not equal its actual size (%" AFS_SIZET_FMT ")\n",
bytesWritten, sizeof(struct volumeHeader));
ERROR_EXIT(TC_INTERNALERROR);
}
volBytesRead = 0;
chunkSize = 0;
while (!endofvolume) { /*w */
- bytesread = 0;
-
/* Check for abort in the middle of writing data */
if (volBytesRead >= chunkSize) {
chunkSize += BIGCHUNK;
hostVolumeHeader.contd = 0;
hostVolumeHeader.magic = TC_VOLENDMAGIC;
hostVolumeHeader.endTime = time(0);
- volumeHeader_hton(&hostVolumeHeader, &buffer[bytesread]);
+ volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)&buffer[bytesread]);
bytesread += sizeof(hostVolumeHeader);
/* End the dump and transaction with the volserver. We end it now, before
- * we make the XBSA call because if XBSA blocks, we could time out on the
+ * we make the XBSA call because if XBSA blocks, we could time out on the
* volserver (After last read, the transaction with the volserver is idle).
*/
rc = rx_EndCall(fromcall, 0);
int action, e;
afs_int32 code = 0, tcode, dvcode;
char ch;
- char retryPrompt();
struct vldbentry vldbEntry;
struct sockaddr_in server;
afs_int32 tapepos;
switch (curDump->vtype) {
case BACKVOL:
- if (!(vldbEntry.flags & BACK_EXISTS)) {
+ if (!(vldbEntry.flags & VLF_BACKEXISTS)) {
ErrorLog(0, taskId, 0, 0,
"Volume %s (%u) failed - Backup volume no longer exists\n",
curDump->name, curDump->vid);
case RWVOL:
for (e = 0; e < vldbEntry.nServers; e++) { /* Find the RW volume */
- if (vldbEntry.serverFlags[e] & ITSRWVOL)
+ if (vldbEntry.serverFlags[e] & VLSF_RWVOL)
break;
}
break;
if (e >= vldbEntry.nServers) { /* Didn't find RO volume */
for (e = 0; e < vldbEntry.nServers; e++) { /* Find the first RO volume */
- if (vldbEntry.serverFlags[e] & ITSROVOL)
+ if (vldbEntry.serverFlags[e] & VLSF_ROVOL)
break;
}
}
curDump->name, curDump->vid);
curDump->hostAddr = 0;
continue;
- break;
}
if (e >= vldbEntry.nServers) {
if (checkAbortByTaskId(taskId))
ERROR_EXIT(TC_ABORTEDBYREQUEST);
- /* Establish connection to volume - UV_ routine expects
- * host address in network order
+ /* Establish connection to volume - UV_ routine expects
+ * host address in network order
*/
if (CONF_XBSA) {
dvcode = xbsaDumpVolume(curDump, dparamsPtr);
case 'r': /* retry */
dparamsPtr->curVolume--; /* redump this volume */
continue;
- break;
case 'o': /* omit */
ErrorLog(1, taskId, 0, 0, "Volume %s (%u) omitted\n",
curDump->name, curDump->vid);
dparamsPtr->curVolume--; /* redump this volume */
continue;
- break;
case DUMP_NORETRYEOT:
ErrorLog(1, taskId, 0, 0,
return (code);
}
-int
-Dumper(struct dumpNode *nodePtr)
+void *
+Dumper(void *param)
{
+ struct dumpNode *nodePtr = (struct dumpNode *)param;
struct dumpRock dparams;
struct butm_tapeInfo tapeInfo;
int pass;
int nodumpvolumes = 0;
char strlevel[5];
char msg[20];
- char finishedMsg1[50];
+ char finishedMsg1[128];
char finishedMsg2[50];
time_t startTime = 0;
time_t endTime = 0;
extern struct deviceSyncNode *deviceLatch;
extern struct tapeConfig globalTapeConfig;
- extern afs_int32 createDump();
+ afs_pthread_setname_self("dumper");
taskId = nodePtr->taskID; /* Get task Id */
setStatus(taskId, DRIVE_WAIT);
EnterDeviceQueue(deviceLatch);
break;
}
- /*
+ /*
* Log the error but ignore it since the dump is effectively done.
* Scantape may assume another volume and ask for next tape.
*/
if (!CONF_XBSA) {
code = butm_WriteEOT(&tapeInfo);
if (code)
- TapeLog(taskId, code, tapeInfo.error,
+ TapeLog(0, taskId, code, tapeInfo.error,
"Warning: Can't write end-of-dump on tape\n");
}
sprintf(line,
"%-5d %02d/%02d/%04d %02d:%02d:%02d "
"%02d/%02d/%04d %02d:%02d:%02d " "%02d:%02d:%02d "
- "%s %d of %d volumes dumped (%ld KB)\n", taskId,
+ "%s %d of %d volumes dumped (%lu KB)\n", taskId,
tmstart.tm_mon + 1, tmstart.tm_mday, tmstart.tm_year + 1900,
tmstart.tm_hour, tmstart.tm_min, tmstart.tm_sec,
tmend.tm_mon + 1, tmend.tm_mday, tmend.tm_year + 1900,
tmend.tm_hour, tmend.tm_min, tmend.tm_sec, hrs, min, sec,
nodePtr->volumeSetName, dumpedvolumes,
dumpedvolumes + failedvolumes,
- dparams.tapeInfoPtr->kBytes + 1);
+ afs_printable_uint32_lu(dparams.tapeInfoPtr->kBytes + 1));
fwrite(line, strlen(line), 1, centralLogIO);
fflush(centralLogIO);
FreeNode(taskId); /* free the dump node */
LeaveDeviceQueue(deviceLatch);
- return (code);
+ return (void *)(intptr_t)(code);
}
#define BELLTIME 60 /* 60 seconds before a bell rings */
* volume parameters describe the volume that failed
* entry:
* volumeName - name of volume
- * volumeId - volume id
+ * volumeId - volume id
* taskId - for job contrl
* fn return:
* character typed by user, one of r, o or a
printf("a - abort, the entire dump\n");
while (1) {
- FFlushInput(stdin);
+ FFlushInput();
putchar(BELLCHAR);
fflush(stdout);
start = time(0);
while (1) {
-#ifdef AFS_PTHREAD_ENV
- code = GetResponseKey(5, &ch); /* ch stores key pressed */
-#else
code = LWP_GetResponseKey(5, &ch); /* ch stores key pressed */
-#endif
if (code == 1)
break; /* input is available */
afs_int32 tapepos, lastpos;
extern struct tapeConfig globalTapeConfig;
- extern struct udbHandleS udbHandle;
askForTape = interactiveFlag;
dparamsPtr->wroteLabel = 0;
/*
* Now have the right tape. Create a new label for the tape
- * Appended labels have the dump's dumpId - labels at beginnings of
+ * Appended labels have the dump's dumpId - labels at beginnings of
* tape have the initial dump's dumpId.
* Appended labels do not increment the useCount.
* Labels at beginnings of tape use the most future expiration of the dump set.
strcpy(vhptr->dumpSetName, nodePtr->dumpSetName);
strcpy(vhptr->preamble, "H++NAME#");
strcpy(vhptr->postamble, "T--NAME#");
-
+
return (code);
}
{
struct volumeHeader volHdr;
+ memset(&volHdr, 0, sizeof(volHdr));
+
strcpy(volHdr.preamble, hostPtr->preamble);
strcpy(volHdr.postamble, hostPtr->postamble);
strcpy(volHdr.volumeName, hostPtr->volumeName);
/* DeleteDump
*
*/
-int
-DeleteDump(struct deleteDumpIf *ptr)
+void *
+DeleteDump(void *param)
{
+ struct deleteDumpIf *ptr = (struct deleteDumpIf *)param;
+
afs_int32 taskId;
afs_int32 rc, code = 0;
afs_uint32 dumpid;
extern struct udbHandleS udbHandle;
extern struct deviceSyncNode *deviceLatch;
+ dumpid = ptr->dumpID;
+ taskId = ptr->taskId; /* Get task Id */
+
+ afs_pthread_setname_self("deletedump");
setStatus(taskId, DRIVE_WAIT);
EnterDeviceQueue(deviceLatch);
clearStatus(taskId, DRIVE_WAIT);
- dumpid = ptr->dumpID;
- taskId = ptr->taskId; /* Get task Id */
-
printf("\n\n");
TapeLog(2, taskId, 0, 0, "Delete Dump %u\n", dumpid);
code = BUTX_DELETENOVOL;
setStatus(taskId, TASK_ERROR);
}
- return (code);
+ return (void *)(uintptr_t)(code);
}
#endif