- Perhaps add read/write programs and/or plugins to FileSets.
- Look at adding Client run command that will use the
port opened by the client.
+- Fix find_device in stored/dircmd.c:462
Documentation to do: (any release a little bit at a time)
- Document query file format.
- Test new I/O error despooling code.
- Sort Scheduled jobs status listing by start time.
- Add priority to Scheduled jobs status listing.
-
* except echo the heartbeat to the Director).
*
*/
-int blast_data_to_storage_daemon(JCR *jcr, char *addr)
+bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
{
BSOCK *sd;
- int stat = 1;
+ bool ok = true;
sd = jcr->store_bsock;
if (!bnet_set_buffer_size(sd, buf_size, BNET_SETBUF_WRITE)) {
set_jcr_job_status(jcr, JS_ErrorTerminated);
Jmsg(jcr, M_FATAL, 0, _("Cannot set buffer size FD->SD.\n"));
- return 0;
+ return false;
}
jcr->buf_size = sd->msglen;
/* Subroutine save_file() is called for each file */
if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, (void *)jcr)) {
- stat = 0; /* error */
+ ok = false; /* error */
set_jcr_job_status(jcr, JS_ErrorTerminated);
- Jmsg(jcr, M_FATAL, 0, _("Find files error.\n"));
+// Jmsg(jcr, M_FATAL, 0, _("Find files error.\n"));
}
stop_heartbeat_monitor(jcr);
free_pool_memory(jcr->compress_buf);
jcr->compress_buf = NULL;
}
- Dmsg1(300, "end blast_data stat=%d\n", stat);
- return stat;
+ Dmsg1(300, "end blast_data stat=%d\n", ok);
+ return ok;
}
/*
*/
-extern int blast_data_to_storage_daemon(JCR *jcr, char *addr);
+extern bool blast_data_to_storage_daemon(JCR *jcr, char *addr);
extern void do_verify(JCR *jcr);
extern void do_verify_volume(JCR *jcr);
extern void do_restore(JCR *jcr);
dcr->jcr = jcr;
dcr->dev = dev;
dcr->block = new_block(dev);
- dcr->record = new_record();
+ dcr->rec = new_record();
dcr->spool_fd = -1;
dcr->max_spool_size = dev->device->max_spool_size;
return dcr;
if (dcr->block) {
free_block(dcr->block);
}
- if (dcr->record) {
- free_record(dcr->record);
+ if (dcr->rec) {
+ free_record(dcr->rec);
}
if (dcr->jcr) {
dcr->jcr->dcr = NULL;
}
if (!write_block_to_dev(dcr, block)) {
- stat = fixup_device_block_write_error(jcr, dev, block);
+ stat = fixup_device_block_write_error(dcr, block);
}
bail_out:
/*
* Write a block to the device
*
- * Returns: 1 on success or EOT
- * 0 on hard error
+ * Returns: true on success or EOT
+ * false on hard error
*/
-int write_block_to_dev(DCR *dcr, DEV_BLOCK *block)
+bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block)
{
ssize_t stat = 0;
uint32_t wlen; /* length to write */
#ifdef NO_TAPE_WRITE_TEST
empty_block(block);
- return 1;
+ return true;
#endif
ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf)));
Dmsg0(100, "return write_block_to_dev with ST_WEOT\n");
dev->dev_errno = ENOSPC;
Jmsg(jcr, M_FATAL, 0, _("Cannot write block. Device at EOM.\n"));
- return 0;
+ return false;
}
wlen = block->binbuf;
if (wlen <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */
Dmsg0(100, "return write_block_to_dev no data to write\n");
- return 1;
+ return true;
}
/*
* Clear to the end of the buffer if it is not full,
}
dev->state |= (ST_EOF | ST_EOT | ST_WEOT);
dev->dev_errno = ENOSPC;
- return 0;
+ return false;
}
/* Limit maximum File size on volume to user specified value */
dev->VolCatInfo.VolCatFiles = dev->file;
dir_update_volume_info(jcr, dev, 0);
dev->dev_errno = ENOSPC;
- return 0;
+ return false;
}
/* Create a JobMedia record so restore can seek */
Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
dcr->VolCatInfo.VolCatName, jcr->Job);
if (!forge_on) {
- return 0;
+ return false;
}
}
dev->file_size = 0; /* reset file size */
}
}
#endif
- return 0;
+ return false;
}
/* We successfully wrote the block, now do housekeeping */
Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num,
wlen);
empty_block(block);
- return 1;
+ return true;
}
/*
stop = -1; /* stop, but do simplified test */
} else {
/* Full test in progress */
- if (!fixup_device_block_write_error(jcr, dev, block)) {
+ if (!fixup_device_block_write_error(jcr->dcr, block)) {
Pmsg1(000, _("Cannot fixup device error. %s\n"), strerror_dev(dev));
ok = false;
unlock_device(dev);
jcr->VolCatInfo.Slot = volnum;
dcr->VolCatInfo.Slot = volnum;
}
-
-#ifdef xxx
-/*
- * Edit codes into ChangerCommand
- * %% = %
- * %a = archive device name
- * %c = changer device name
- * %f = Client's name
- * %j = Job name
- * %o = command
- * %s = Slot base 0
- * %S = Slot base 1
- * %v = Volume name
- *
- *
- * omsg = edited output message
- * imsg = input string containing edit codes (%x)
- * cmd = command string (load, unload, ...)
- *
- */
-static char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd)
-{
- char *p;
- const char *str;
- char add[20];
-
- *omsg = 0;
- Dmsg1(400, "edit_device_codes: %s\n", imsg);
- for (p=imsg; *p; p++) {
- if (*p == '%') {
- switch (*++p) {
- case '%':
- str = "%";
- break;
- case 'a':
- str = dev_name(jcr->device->dev);
- break;
- case 'c':
- str = NPRT(jcr->device->changer_name);
- break;
- case 'o':
- str = NPRT(cmd);
- break;
- case 's':
- sprintf(add, "%d", jcr->VolCatInfo.Slot - 1);
- str = add;
- break;
- case 'S':
- sprintf(add, "%d", jcr->VolCatInfo.Slot);
- str = add;
- break;
- case 'j': /* Job name */
- str = jcr->Job;
- break;
- case 'v':
- str = NPRT(jcr->VolumeName);
- break;
- case 'f':
- str = NPRT(jcr->client_name);
- break;
-
- default:
- add[0] = '%';
- add[1] = *p;
- add[2] = 0;
- str = add;
- break;
- }
- } else {
- add[0] = *p;
- add[1] = 0;
- str = add;
- }
- Dmsg1(400, "add_str %s\n", str);
- pm_strcat(&omsg, (char *)str);
- Dmsg1(400, "omsg=%s\n", omsg);
- }
- return omsg;
-}
-#endif
-
-#ifdef xxxx_needed
-/*
- * We are called here from "unfill" for each record on the tape.
- */
-static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
-{
- SESSION_LABEL label;
-
- if (stop > 1 && !dumped) { /* on second tape */
- dumped = 1;
- if (verbose) {
- dump_block(block, "First block on second tape");
- }
- Pmsg4(-1, "Blk: FileIndex=%d: block=%u size=%d vol=%s\n",
- rec->FileIndex, block->BlockNumber, block->block_len, dev->VolHdr.VolName);
- Pmsg6(-1, " Rec: VId=%d VT=%d FI=%s Strm=%s len=%d state=%x\n",
- rec->VolSessionId, rec->VolSessionTime,
- FI_to_ascii(rec->FileIndex), stream_to_ascii(rec->Stream, rec->FileIndex),
- rec->data_len, rec->state);
- }
- if (rec->FileIndex < 0) {
- if (verbose > 1) {
- dump_label_record(dev, rec, 1);
- }
- switch (rec->FileIndex) {
- case PRE_LABEL:
- Pmsg0(-1, "Volume is prelabeled. This tape cannot be scanned.\n");
- return 1;;
- case VOL_LABEL:
- unser_volume_label(dev, rec);
- Pmsg3(-1, "VOL_LABEL: block=%u size=%d vol=%s\n", block->BlockNumber,
- block->block_len, dev->VolHdr.VolName);
- stop++;
- break;
- case SOS_LABEL:
- unser_session_label(&label, rec);
- Pmsg1(-1, "SOS_LABEL: JobId=%u\n", label.JobId);
- break;
- case EOS_LABEL:
- unser_session_label(&label, rec);
- Pmsg2(-1, "EOS_LABEL: block=%u JobId=%u\n", block->BlockNumber,
- label.JobId);
- break;
- case EOM_LABEL:
- Pmsg0(-1, "EOM_LABEL:\n");
- break;
- case EOT_LABEL: /* end of all tapes */
- char ec1[50];
-
- if (LastBlock != block->BlockNumber) {
- VolBytes += block->block_len;
- }
- LastBlock = block->BlockNumber;
- now = time(NULL);
- now -= jcr->run_time;
- if (now <= 0) {
- now = 1;
- }
- kbs = (double)VolBytes / (1000 * now);
- Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
- edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
-
- Pmsg0(000, "End of all tapes.\n");
-
- break;
- default:
- break;
- }
- return 1;
- }
- if (++file_index != rec->FileIndex) {
- Pmsg3(000, "Incorrect FileIndex in Block %u. Got %d, expected %d.\n",
- block->BlockNumber, rec->FileIndex, file_index);
- }
- if (LastBlock != block->BlockNumber) {
- VolBytes += block->block_len;
- }
- if ((block->BlockNumber != LastBlock) && (block->BlockNumber % 50000) == 0) {
- char ec1[50];
- now = time(NULL);
- now -= jcr->run_time;
- if (now <= 0) {
- now = 1;
- }
- kbs = (double)VolBytes / (1000 * now);
- Pmsg3(000, "Read block=%u, VolBytes=%s rate=%.1f KB/s\n", block->BlockNumber,
- edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
- }
- LastBlock = block->BlockNumber;
- if (end_of_tape) {
- Pmsg1(000, "End of all blocks. Block=%u\n", block->BlockNumber);
- }
- return 1;
-}
-#endif
#ifndef __DEV_H
#define __DEV_H 1
-#undef DCR /* used by Bacula */
+#undef DCR /* used by Bacula */
/* #define NEW_LOCK 1 */
-#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev))
+#define new_lock_device(dev) _new_lock_device(__FILE__, __LINE__, (dev))
#define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state))
-#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev))
+#define new_unlock_device(dev) _new_unlock_device(__FILE__, __LINE__, (dev))
#define lock_device(d) _lock_device(__FILE__, __LINE__, (d))
#define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d))
};
/* Generic status bits returned from status_dev() */
-#define BMT_TAPE (1<<0) /* is tape device */
-#define BMT_EOF (1<<1) /* just read EOF */
-#define BMT_BOT (1<<2) /* at beginning of tape */
-#define BMT_EOT (1<<3) /* end of tape reached */
-#define BMT_SM (1<<4) /* DDS setmark */
-#define BMT_EOD (1<<5) /* DDS at end of data */
-#define BMT_WR_PROT (1<<6) /* tape write protected */
-#define BMT_ONLINE (1<<7) /* tape online */
-#define BMT_DR_OPEN (1<<8) /* tape door open */
-#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */
+#define BMT_TAPE (1<<0) /* is tape device */
+#define BMT_EOF (1<<1) /* just read EOF */
+#define BMT_BOT (1<<2) /* at beginning of tape */
+#define BMT_EOT (1<<3) /* end of tape reached */
+#define BMT_SM (1<<4) /* DDS setmark */
+#define BMT_EOD (1<<5) /* DDS at end of data */
+#define BMT_WR_PROT (1<<6) /* tape write protected */
+#define BMT_ONLINE (1<<7) /* tape online */
+#define BMT_DR_OPEN (1<<8) /* tape door open */
+#define BMT_IM_REP_EN (1<<9) /* immediate report enabled */
/* Test capabilities */
#define dev_cap(dev, cap) ((dev)->capabilities & (cap))
/* Bits for device capabilities */
-#define CAP_EOF (1<<0) /* has MTWEOF */
-#define CAP_BSR (1<<1) /* has MTBSR */
-#define CAP_BSF (1<<2) /* has MTBSF */
-#define CAP_FSR (1<<3) /* has MTFSR */
-#define CAP_FSF (1<<4) /* has MTFSF */
-#define CAP_EOM (1<<5) /* has MTEOM */
-#define CAP_REM (1<<6) /* is removable media */
-#define CAP_RACCESS (1<<7) /* is random access device */
-#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */
-#define CAP_LABEL (1<<9) /* Label blank tapes */
-#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */
-#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */
+#define CAP_EOF (1<<0) /* has MTWEOF */
+#define CAP_BSR (1<<1) /* has MTBSR */
+#define CAP_BSF (1<<2) /* has MTBSF */
+#define CAP_FSR (1<<3) /* has MTFSR */
+#define CAP_FSF (1<<4) /* has MTFSF */
+#define CAP_EOM (1<<5) /* has MTEOM */
+#define CAP_REM (1<<6) /* is removable media */
+#define CAP_RACCESS (1<<7) /* is random access device */
+#define CAP_AUTOMOUNT (1<<8) /* Read device at start to see what is there */
+#define CAP_LABEL (1<<9) /* Label blank tapes */
+#define CAP_ANONVOLS (1<<10) /* Mount without knowing volume name */
+#define CAP_ALWAYSOPEN (1<<11) /* always keep device open */
#define CAP_AUTOCHANGER (1<<12) /* AutoChanger */
#define CAP_OFFLINEUNMOUNT (1<<13) /* Offline before unmount */
-#define CAP_STREAM (1<<14) /* Stream device */
-#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */
-#define CAP_FASTFSF (1<<16) /* Fast forward space file */
-#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */
+#define CAP_STREAM (1<<14) /* Stream device */
+#define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */
+#define CAP_FASTFSF (1<<16) /* Fast forward space file */
+#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */
#define CAP_CLOSEONPOLL (1<<18) /* Close device on polling */
/* Test state */
#define dev_state(dev, st_state) ((dev)->state & (st_state))
/* Device state bits */
-#define ST_OPENED (1<<0) /* set when device opened */
-#define ST_TAPE (1<<1) /* is a tape device */
-#define ST_FILE (1<<2) /* is a file device */
-#define ST_FIFO (1<<3) /* is a fifo device */
-#define ST_PROG (1<<4) /* is a program device */
-#define ST_LABEL (1<<5) /* label found */
+#define ST_OPENED (1<<0) /* set when device opened */
+#define ST_TAPE (1<<1) /* is a tape device */
+#define ST_FILE (1<<2) /* is a file device */
+#define ST_FIFO (1<<3) /* is a fifo device */
+#define ST_PROG (1<<4) /* is a program device */
+#define ST_LABEL (1<<5) /* label found */
#define ST_MALLOC (1<<6) /* dev packet malloc'ed in init_dev() */
-#define ST_APPEND (1<<7) /* ready for Bacula append */
-#define ST_READ (1<<8) /* ready for Bacula read */
-#define ST_EOT (1<<9) /* at end of tape */
-#define ST_WEOT (1<<10) /* Got EOT on write */
-#define ST_EOF (1<<11) /* Read EOF i.e. zero bytes */
-#define ST_NEXTVOL (1<<12) /* Start writing on next volume */
-#define ST_SHORT (1<<13) /* Short block read */
+#define ST_APPEND (1<<7) /* ready for Bacula append */
+#define ST_READ (1<<8) /* ready for Bacula read */
+#define ST_EOT (1<<9) /* at end of tape */
+#define ST_WEOT (1<<10) /* Got EOT on write */
+#define ST_EOF (1<<11) /* Read EOF i.e. zero bytes */
+#define ST_NEXTVOL (1<<12) /* Start writing on next volume */
+#define ST_SHORT (1<<13) /* Short block read */
/* dev_blocked states (mutually exclusive) */
enum {
- BST_NOT_BLOCKED = 0, /* not blocked */
- BST_UNMOUNTED, /* User unmounted device */
- BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */
- BST_DOING_ACQUIRE, /* Opening/validating/moving tape */
- BST_WRITING_LABEL, /* Labeling a tape */
+ BST_NOT_BLOCKED = 0, /* not blocked */
+ BST_UNMOUNTED, /* User unmounted device */
+ BST_WAITING_FOR_SYSOP, /* Waiting for operator to mount tape */
+ BST_DOING_ACQUIRE, /* Opening/validating/moving tape */
+ BST_WRITING_LABEL, /* Labeling a tape */
BST_UNMOUNTED_WAITING_FOR_SYSOP, /* Closed by user during mount request */
- BST_MOUNT /* Mount request */
+ BST_MOUNT /* Mount request */
};
/* Volume Catalog Information structure definition */
struct VOLUME_CAT_INFO {
/* Media info for the current Volume */
- uint32_t VolCatJobs; /* number of jobs on this Volume */
- uint32_t VolCatFiles; /* Number of files */
- uint32_t VolCatBlocks; /* Number of blocks */
- uint64_t VolCatBytes; /* Number of bytes written */
- uint32_t VolCatMounts; /* Number of mounts this volume */
- uint32_t VolCatErrors; /* Number of errors this volume */
- uint32_t VolCatWrites; /* Number of writes this volume */
- uint32_t VolCatReads; /* Number of reads this volume */
- uint64_t VolCatRBytes; /* Number of bytes read */
- uint32_t VolCatRecycles; /* Number of recycles this volume */
- int32_t Slot; /* Slot in changer */
- bool InChanger; /* Set if vol in current magazine */
- uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */
- uint32_t VolCatMaxFiles; /* Maximum files to write to volume */
- uint64_t VolCatMaxBytes; /* Max bytes to write to volume */
+ uint32_t VolCatJobs; /* number of jobs on this Volume */
+ uint32_t VolCatFiles; /* Number of files */
+ uint32_t VolCatBlocks; /* Number of blocks */
+ uint64_t VolCatBytes; /* Number of bytes written */
+ uint32_t VolCatMounts; /* Number of mounts this volume */
+ uint32_t VolCatErrors; /* Number of errors this volume */
+ uint32_t VolCatWrites; /* Number of writes this volume */
+ uint32_t VolCatReads; /* Number of reads this volume */
+ uint64_t VolCatRBytes; /* Number of bytes read */
+ uint32_t VolCatRecycles; /* Number of recycles this volume */
+ int32_t Slot; /* Slot in changer */
+ bool InChanger; /* Set if vol in current magazine */
+ uint32_t VolCatMaxJobs; /* Maximum Jobs to write to volume */
+ uint32_t VolCatMaxFiles; /* Maximum files to write to volume */
+ uint64_t VolCatMaxBytes; /* Max bytes to write to volume */
uint64_t VolCatCapacityBytes; /* capacity estimate */
- uint64_t VolReadTime; /* time spent reading */
- uint64_t VolWriteTime; /* time spent writing this Volume */
- char VolCatStatus[20]; /* Volume status */
+ uint64_t VolReadTime; /* time spent reading */
+ uint64_t VolWriteTime; /* time spent writing this Volume */
+ char VolCatStatus[20]; /* Volume status */
char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */
-};
+};
typedef struct s_steal_lock {
- pthread_t no_wait_id; /* id of no wait thread */
- int dev_blocked; /* state */
- int dev_prev_blocked; /* previous blocked state */
+ pthread_t no_wait_id; /* id of no wait thread */
+ int dev_blocked; /* state */
+ int dev_prev_blocked; /* previous blocked state */
} bsteal_lock_t;
-struct DEVRES; /* Device resource defined in stored_conf.h */
+struct DEVRES; /* Device resource defined in stored_conf.h */
/*
* Device structure definition. There is one of these for
*/
struct DEVICE {
public:
- DEVICE *next; /* pointer to next open device */
- DEVICE *prev; /* pointer to prev open device */
- JCR *attached_jcrs; /* attached JCR list */
- dlist *attached_dcrs; /* attached DCR list */
- pthread_mutex_t mutex; /* access control */
+ DEVICE *next; /* pointer to next open device */
+ DEVICE *prev; /* pointer to prev open device */
+ JCR *attached_jcrs; /* attached JCR list */
+ dlist *attached_dcrs; /* attached DCR list */
+ pthread_mutex_t mutex; /* access control */
pthread_mutex_t spool_mutex; /* mutex for updating spool_size */
- pthread_cond_t wait; /* thread wait variable */
+ pthread_cond_t wait; /* thread wait variable */
pthread_cond_t wait_next_vol; /* wait for tape to be mounted */
- pthread_t no_wait_id; /* this thread must not wait */
- int dev_blocked; /* set if we must wait (i.e. change tape) */
- int dev_prev_blocked; /* previous blocked state */
- int num_waiting; /* number of threads waiting */
- int num_writers; /* number of writing threads */
- int use_count; /* usage count on this device */
- int fd; /* file descriptor */
- int capabilities; /* capabilities mask */
- int state; /* state mask */
- int dev_errno; /* Our own errno */
- int mode; /* read/write modes */
- uint32_t drive_index; /* Autochanger drive index */
- POOLMEM *dev_name; /* device name */
- char *errmsg; /* nicely edited error message */
- uint32_t block_num; /* current block number base 0 */
- uint32_t file; /* current file number base 0 */
- uint64_t file_addr; /* Current file read/write address */
- uint64_t file_size; /* Current file size */
- uint32_t EndBlock; /* last block written */
- uint32_t EndFile; /* last file written */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint64_t max_volume_size; /* max bytes to put on one volume */
- uint64_t max_file_size; /* max file size to put in one file on volume */
- uint64_t volume_capacity; /* advisory capacity */
- uint64_t max_spool_size; /* maximum spool file size */
- uint64_t spool_size; /* curren spool size */
- uint32_t max_rewind_wait; /* max secs to allow for rewind */
- uint32_t max_open_wait; /* max secs to allow for open */
- uint32_t max_open_vols; /* max simultaneous open volumes */
- utime_t vol_poll_interval; /* interval between polling Vol mount */
- DEVRES *device; /* pointer to Device Resource */
- btimer_t *tid; /* timer id */
+ pthread_t no_wait_id; /* this thread must not wait */
+ int dev_blocked; /* set if we must wait (i.e. change tape) */
+ int dev_prev_blocked; /* previous blocked state */
+ int num_waiting; /* number of threads waiting */
+ int num_writers; /* number of writing threads */
+ int use_count; /* usage count on this device */
+ int fd; /* file descriptor */
+ int capabilities; /* capabilities mask */
+ int state; /* state mask */
+ int dev_errno; /* Our own errno */
+ int mode; /* read/write modes */
+ uint32_t drive_index; /* Autochanger drive index */
+ POOLMEM *dev_name; /* device name */
+ char *errmsg; /* nicely edited error message */
+ uint32_t block_num; /* current block number base 0 */
+ uint32_t file; /* current file number base 0 */
+ uint64_t file_addr; /* Current file read/write address */
+ uint64_t file_size; /* Current file size */
+ uint32_t EndBlock; /* last block written */
+ uint32_t EndFile; /* last file written */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint64_t max_volume_size; /* max bytes to put on one volume */
+ uint64_t max_file_size; /* max file size to put in one file on volume */
+ uint64_t volume_capacity; /* advisory capacity */
+ uint64_t max_spool_size; /* maximum spool file size */
+ uint64_t spool_size; /* curren spool size */
+ uint32_t max_rewind_wait; /* max secs to allow for rewind */
+ uint32_t max_open_wait; /* max secs to allow for open */
+ uint32_t max_open_vols; /* max simultaneous open volumes */
+ utime_t vol_poll_interval; /* interval between polling Vol mount */
+ DEVRES *device; /* pointer to Device Resource */
+ btimer_t *tid; /* timer id */
- VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
- VOLUME_LABEL VolHdr; /* Actual volume label */
+ VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
+ VOLUME_LABEL VolHdr; /* Actual volume label */
/* Device wait times ***FIXME*** look at durations */
char BadVolName[MAX_NAME_LENGTH]; /* Last wrong Volume mounted */
- bool poll; /* set to poll Volume */
+ bool poll; /* set to poll Volume */
int min_wait;
int max_wait;
int max_num_wait;
};
/*
- * Device Context (or Control) Record.
- * There is one of these records for each Job that is using
+ * Device Context (or Control) Record.
+ * There is one of these records for each Job that is using
* the device. Items in this record are "local" to the Job and
* do not affect other Jobs.
*/
struct DCR {
- dlink dev_link; /* link to attach to dev */
- JCR *jcr; /* pointer to JCR */
- DEVICE *dev; /* pointer to device */
- DEV_BLOCK *block; /* pointer to block */
- DEV_RECORD *record; /* pointer to record */
- bool spool_data; /* set to spool data */
- bool spooling; /* set when actually spooling */
- bool dev_locked; /* set if dev already locked */
- int spool_fd; /* fd if spooling */
- bool NewVol; /* set if new Volume mounted */
- bool WroteVol; /* set if Volume written */
- bool NewFile; /* set when EOF written */
- uint32_t VolFirstIndex; /* First file index this Volume */
- uint32_t VolLastIndex; /* Last file index this Volume */
- uint32_t FileIndex; /* Current File Index */
- uint32_t EndFile; /* End file written */
- uint32_t StartFile; /* Start write file */
- uint32_t StartBlock; /* Start write block */
- uint32_t EndBlock; /* Ending block written */
- int64_t spool_size; /* Current spool size */
- int64_t max_spool_size; /* Max job spool size */
+ dlink dev_link; /* link to attach to dev */
+ JCR *jcr; /* pointer to JCR */
+ DEVICE *dev; /* pointer to device */
+ DEV_BLOCK *block; /* pointer to block */
+ DEV_RECORD *rec; /* pointer to record */
+ bool spool_data; /* set to spool data */
+ bool spooling; /* set when actually spooling */
+ bool dev_locked; /* set if dev already locked */
+ int spool_fd; /* fd if spooling */
+ bool NewVol; /* set if new Volume mounted */
+ bool WroteVol; /* set if Volume written */
+ bool NewFile; /* set when EOF written */
+ uint32_t VolFirstIndex; /* First file index this Volume */
+ uint32_t VolLastIndex; /* Last file index this Volume */
+ uint32_t FileIndex; /* Current File Index */
+ uint32_t EndFile; /* End file written */
+ uint32_t StartFile; /* Start write file */
+ uint32_t StartBlock; /* Start write block */
+ uint32_t EndBlock; /* Ending block written */
+ int64_t spool_size; /* Current spool size */
+ int64_t max_spool_size; /* Max job spool size */
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
- VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
+ VOLUME_CAT_INFO VolCatInfo; /* Catalog info for desired volume */
};
* dependent. Arrgggg!
*/
#ifndef MTEOM
-#ifdef MTSEOD
+#ifdef MTSEOD
#define MTEOM MTSEOD
#endif
#ifdef MTEOD
*
* Note, we are called only from one place in block.c
*
- * Returns: 1 on success
- * 0 on failure
+ * Returns: true on success
+ * false on failure
*/
-int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block)
{
uint32_t stat;
char PrevVolName[MAX_NAME_LENGTH];
char b1[30], b2[30];
time_t wait_time;
char dt[MAX_TIME_LENGTH];
+ JCR *jcr = dcr->jcr;
+ DEVICE *dev = dcr->dev;
wait_time = time(NULL);
stat = status_dev(dev);
if (!(stat & BMT_EOD)) {
- return 0; /* this really shouldn't happen */
+ return false; /* this really shouldn't happen */
}
Dmsg0(100, "======= Got EOD ========\n");
jcr->VolCatInfo.VolCatName, jcr->Job);
P(dev->mutex);
unblock_device(dev);
- return 0;
+ return false;
}
bstrncpy(dev->VolCatInfo.VolCatStatus, "Full", sizeof(dev->VolCatInfo.VolCatStatus));
if (!dir_update_volume_info(jcr, dev, 0)) { /* send Volume info to Director */
P(dev->mutex);
unblock_device(dev);
- return 0; /* device locked */
+ return false; /* device locked */
}
Dmsg0(100, "Back from update_vol_info\n");
free_block(label_blk);
P(dev->mutex);
unblock_device(dev);
- return 0; /* device locked */
+ return false; /* device locked */
}
P(dev->mutex); /* lock again */
* empty label_blk, and nothing will be written.
*/
Dmsg0(190, "write label block to dev\n");
- if (!write_block_to_dev(jcr->dcr, label_blk)) {
+ if (!write_block_to_dev(dcr, label_blk)) {
Pmsg1(0, "write_block_to_device Volume label failed. ERR=%s",
strerror_dev(dev));
free_block(label_blk);
unblock_device(dev);
- return 0; /* device locked */
+ return false; /* device locked */
}
free_block(label_blk);
/* Write overflow block to device */
Dmsg0(190, "Write overflow block to dev\n");
- if (!write_block_to_dev(jcr->dcr, block)) {
+ if (!write_block_to_dev(dcr, block)) {
Pmsg1(0, "write_block_to_device overflow block failed. ERR=%s",
strerror_dev(dev));
unblock_device(dev);
- return 0; /* device locked */
+ return false; /* device locked */
}
unblock_device(dev);
- return 1; /* device locked */
+ return true; /* device locked */
}
/*
static int unmount_cmd(JCR *jcr);
static int autochanger_cmd(JCR *sjcr);
static int do_label(JCR *jcr, int relabel);
-static bool find_device(JCR *jcr, char *dname);
+static DEVICE *find_device(JCR *jcr, char *dname);
static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot);
static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
char *newname, char *poolname,
bnet_sig(jcr->file_bsock, BNET_TERMINATE);
}
/* If thread waiting on mount, wake him */
- if (jcr->device && jcr->device->dev &&
- (jcr->device->dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
- jcr->device->dev->dev_blocked == BST_UNMOUNTED ||
- jcr->device->dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
- pthread_cond_signal(&jcr->device->dev->wait_next_vol);
+ if (jcr->dcr && jcr->dcr->dev &&
+ (jcr->dcr->dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
+ jcr->dcr->dev->dev_blocked == BST_UNMOUNTED ||
+ jcr->dcr->dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
+ pthread_cond_signal(&jcr->dcr->dev->wait_next_vol);
}
bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job);
free_jcr(jcr);
unbash_spaces(oldname);
unbash_spaces(poolname);
unbash_spaces(mtype);
- if (find_device(jcr, dname)) {
+ dev = find_device(jcr, dname);
+ if (dev) {
/******FIXME**** compare MediaTypes */
- dev = jcr->device->dev;
-
P(dev->mutex); /* Use P to avoid indefinite block */
if (!(dev->state & ST_OPENED)) {
label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
/* Fall through wanted! */
case VOL_IO_ERROR:
case VOL_NO_LABEL:
- if (!write_new_volume_label_to_dev(jcr, jcr->device->dev, newname, poolname)) {
+ if (!write_new_volume_label_to_dev(jcr, dev, newname, poolname)) {
bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
break;
}
return stat;
}
-static bool find_device(JCR *jcr, char *dname)
+static DEVICE *find_device(JCR *jcr, char *dname)
{
DEVRES *device = NULL;
bool found = false;
}
}
if (found) {
+ /*
+ * ****FIXME***** device->dev may not point to right device
+ * if there are multiple devices open
+ */
jcr->dcr = new_dcr(jcr, device->dev);
+ UnlockRes();
+ return jcr->dcr->dev;
}
UnlockRes();
- return found;
+ return NULL;
}
dname = get_memory(dir->msglen+1);
if (sscanf(dir->msg, "mount %s", dname) == 1) {
- if (find_device(jcr, dname)) {
+ dev = find_device(jcr, dname);
+ if (dev) {
DEV_BLOCK *block;
- dev = jcr->device->dev;
P(dev->mutex); /* Use P to avoid indefinite block */
switch (dev->dev_blocked) { /* device blocked? */
case BST_WAITING_FOR_SYSOP:
dname = get_memory(dir->msglen+1);
if (sscanf(dir->msg, "unmount %s", dname) == 1) {
- if (find_device(jcr, dname)) {
- dev = jcr->device->dev;
+ dev = find_device(jcr, dname);
+ if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!(dev->state & ST_OPENED)) {
Dmsg0(90, "Device already unmounted\n");
dname = get_memory(dir->msglen+1);
if (sscanf(dir->msg, "release %s", dname) == 1) {
- if (find_device(jcr, dname)) {
- dev = jcr->device->dev;
+ dev = find_device(jcr, dname);
+ if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!(dev->state & ST_OPENED)) {
Dmsg0(90, "Device already released\n");
dname = get_memory(dir->msglen+1);
if (sscanf(dir->msg, "autochanger list %s ", dname) == 1) {
- if (find_device(jcr, dname)) {
- dev = jcr->device->dev;
+ dev = find_device(jcr, dname);
+ if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev_is_tape(dev)) {
bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), dev_name(dev));
dname = get_memory(dir->msglen+1);
if (sscanf(dir->msg, "readlabel %s Slot=%d", dname, &Slot) == 2) {
- if (find_device(jcr, dname)) {
- dev = jcr->device->dev;
-
+ dev = find_device(jcr, dname);
+ if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev_state(dev, ST_OPENED)) {
read_volume_label(jcr, dev, Slot);
}
/* Write session label
- * Returns: 0 on failure
- * 1 on success
+ * Returns: false on failure
+ * true on success
*/
-int write_session_label(JCR *jcr, DEV_BLOCK *block, int label)
+bool write_session_label(JCR *jcr, DEV_BLOCK *block, int label)
{
- DEVICE *dev = jcr->device->dev;
DCR *dcr = jcr->dcr;
+ DEVICE *dev = dcr->dev;
DEV_RECORD *rec;
rec = new_record();
Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
dev_vol_name(dev), strerror(errno));
free_record(rec);
- return 0;
+ return false;
}
}
if (!write_record_to_block(block, rec)) {
Jmsg(jcr, M_FATAL, 0, _("Error writing Session label to %s: %s\n"),
dev_vol_name(dev), strerror(errno));
free_record(rec);
- return 0;
+ return false;
}
Dmsg6(20, "Write sesson_label record JobId=%d FI=%s SessId=%d Strm=%s len=%d\n\
free_record(rec);
Dmsg2(20, "Leave write_session_label Block=%d File=%d\n",
dev->block_num, dev->file);
- return 1;
+ return true;
}
void dump_volume_label(DEVICE *dev)
*/
/*
- Copyright (C) 2000-2003 Kern Sibbald and John Walker
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
void empty_block(DEV_BLOCK *block);
void free_block(DEV_BLOCK *block);
int write_block_to_device(DCR *dcr, DEV_BLOCK *block);
-int write_block_to_dev(DCR *dcr, DEV_BLOCK *block);
+bool write_block_to_dev(DCR *dcr, DEV_BLOCK *block);
void print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
void ser_block_header(DEV_BLOCK *block);
/* From device.c */
int open_device(JCR *jcr, DEVICE *dev);
int first_open_device(DEVICE *dev);
-int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+bool fixup_device_block_write_error(DCR *dcr, DEV_BLOCK *block);
void _lock_device(const char *file, int line, DEVICE *dev);
void _unlock_device(const char *file, int line, DEVICE *dev);
void _block_device(const char *file, int line, DEVICE *dev, int state);
void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
bool write_new_volume_label_to_dev(JCR *jcr, DEVICE *dev, const char *VolName, const char *PoolName);
-int write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
+bool write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
bool write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
void dump_volume_label(DEVICE *dev);
void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
/*
* Read Data and send to File Daemon
- * Returns: 0 on failure
- * 1 on success
+ * Returns: false on failure
+ * true on success
*/
bool do_read_data(JCR *jcr)
{
Dmsg0(20, "Start read data.\n");
- dev = jcr->device->dev;
-
- Dmsg1(10, "bstored>filed: %s\n", fd->msg);
-
if (!bnet_set_buffer_size(fd, jcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) {
return false;
}
- Dmsg1(20, "Begin read device=%s\n", dev_name(dev));
-
create_vol_list(jcr);
if (jcr->NumVolumes == 0) {
Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n"));
return false;
}
+ dev = jcr->dcr->dev;
+ Dmsg1(20, "Begin read device=%s\n", dev_name(dev));
+
/* Tell File daemon we will send data */
bnet_fsend(fd, OK_data);
ok = read_records(jcr, dev, record_cb, mount_next_read_volume);