-2003-05-20 Version 1.31 Beta 22May03
+2003-05-22 Version 1.31 Beta 22May03
- I discovered that C++ permits "prototyping" structures e.g. struct A; is
a valid statement. This permitted me to eliminate all the void *jcr, in
favor of JCR *jcr, which pointed out a number of bugs in block.c.
PSCMD="ps -e -o pid,comm"
PFILES="${PFILES} \
platforms/aix/Makefile"
+ TAPEDRIVE="/dev/rmt0.1"
;;
alpha)
DISTVER=`uname -r`
PSCMD="ps -e -o pid,comm"
PFILES="${PFILES} \
platforms/aix/Makefile"
+ TAPEDRIVE="/dev/rmt0.1"
;;
alpha)
DISTVER=`uname -r`
- Figure out how to use ssh or stunnel to protect Bacula communications.
For 1.31 release:
+- Add SDWriteSeqNo to SD, and probably Read on FD side.
+- Make sure all restore counters are working correctly in the FD.
+- When all cassettes in magazine are used, got:
+ 22-May-2003 18:24 undef-sd: 3304 Autochanger "load slot 1" status is OK.
+ 22-May-2003 18:24 undef-sd: NightlySave.2003-05-22_14.08.16 Warning: mount.c:245 Director wanted Volume "TestVolume0009".
+ Current Volume "TestVolume0005" not acceptable because:
+ 1998 Volume "TestVolume0005" not Append or Recycle.
+ 22-May-2003 18:24 undef-sd: NightlySave.2003-05-22_14.08.16 Error: Autochanger Volume "TestVolume0009" not found in slot 1.
+ Setting slot to zero in catalog.
+ 22-May-2003 18:24 undef-sd: Please mount Volume "TestVolume0009" on Storage Device "ARCHIVE 4586" for Job NightlySave.2003-05-22_14
+ .08.16
+ Use "mount" command to release Job.
+ 22-May-2003 19:24 undef-sd: Please mount Volume "TestVolume0009" on Storage Device "ARCHIVE 4586" for Job NightlySave.2003-05-22_14
+ .08.16
+ Use "mount" command to release Job.
+
+- SD Bytes Read is wrong.
+- Configure mtx-changer to have correct path to mtx.
- Look at ALL higher level routines that call block.c to be sure
they don't expect something in errmsg.
- Fix Verify VolumeToCatalog to use BSRs -- it is broken.
* it also contains fields found in the JobMedia record.
*/
/* Job record */
-typedef struct {
+struct JOB_DBR {
JobId_t JobId;
char Job[MAX_NAME_LENGTH]; /* Job unique name */
char Name[MAX_NAME_LENGTH]; /* Job base name */
char cEndTime[MAX_TIME_LENGTH];
/* Extra stuff not in DB */
faddr_t rec_addr;
-} JOB_DBR;
+};
/* Job Media information used to create the media records
* for each Volume used for the job.
*/
/* JobMedia record */
-typedef struct {
+struct JOBMEDIA_DBR {
uint32_t JobMediaId; /* record id */
JobId_t JobId; /* JobId */
uint32_t MediaId; /* MediaId */
uint32_t EndFile; /* End file on Volume */
uint32_t StartBlock; /* start block on tape */
uint32_t EndBlock; /* last block */
-} JOBMEDIA_DBR;
+};
+
/* Volume Parameter structure */
-typedef struct {
+struct VOL_PARAMS {
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
uint32_t FirstIndex; /* First index this Volume */
uint32_t LastIndex; /* Last index this Volume */
uint32_t EndFile; /* End file on Volume */
uint32_t StartBlock; /* start block on tape */
uint32_t EndBlock; /* last block */
-} VOL_PARAMS;
+};
/* Attributes record -- NOT same as in database because
* in general, this "record" creates multiple database
* records (e.g. pathname, filename, fileattributes).
*/
-typedef struct {
+struct ATTR_DBR {
char *fname; /* full path & filename */
char *link; /* link if any */
char *attr; /* attributes statp */
uint32_t PathId;
uint32_t FilenameId;
FileId_t FileId;
-} ATTR_DBR;
+};
/* File record -- same format as database */
-typedef struct {
+struct FILE_DBR {
FileId_t FileId;
uint32_t FileIndex;
JobId_t JobId;
/* int Status; */
char SIG[50];
int SigType; /* NO_SIG/MD5_SIG/SHA1_SIG */
-} FILE_DBR;
+};
/* Pool record -- same format as database */
-typedef struct {
+struct POOL_DBR {
uint32_t PoolId;
char Name[MAX_NAME_LENGTH]; /* Pool name */
uint32_t NumVols; /* total number of volumes */
char LabelFormat[MAX_NAME_LENGTH];
/* Extra stuff not in DB */
faddr_t rec_addr;
-} POOL_DBR;
+};
/* Media record -- same as the database */
-typedef struct {
+struct MEDIA_DBR {
uint32_t MediaId; /* Unique volume id */
char VolumeName[MAX_NAME_LENGTH]; /* Volume name */
char MediaType[MAX_NAME_LENGTH]; /* Media type */
char cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */
char cLastWritten[MAX_TIME_LENGTH]; /* LastWritten returned from DB */
char cLabelData[MAX_TIME_LENGTH]; /* LabelData returned from DB */
-} MEDIA_DBR;
+};
/* Client record -- same as the database */
-typedef struct {
+struct CLIENT_DBR {
uint32_t ClientId; /* Unique Client id */
int AutoPrune;
utime_t FileRetention;
utime_t JobRetention;
char Name[MAX_NAME_LENGTH]; /* Client name */
char Uname[256]; /* Uname for client */
-} CLIENT_DBR;
+};
/* FileSet record -- same as the database */
-typedef struct {
+struct FILESET_DBR {
uint32_t FileSetId; /* Unique FileSet id */
char FileSet[MAX_NAME_LENGTH]; /* FileSet name */
char MD5[50]; /* MD5 signature of include/exclude */
-} FILESET_DBR;
+};
#include "protos.h"
/* Context for insert_tree_handler() */
-typedef struct s_tree_ctx {
+struct TREE_CTX {
TREE_ROOT *root; /* root */
TREE_NODE *node; /* current node */
TREE_NODE *avail_node; /* unused node last insert */
int cnt; /* count for user feedback */
UAContext *ua;
-} TREE_CTX;
+};
/* Main structure for obtaining JobIds */
-typedef struct s_jobids {
+struct JobIds {
utime_t JobTDate;
uint32_t TotalFiles;
char ClientName[MAX_NAME_LENGTH];
char JobIds[200];
STORE *store;
-} JobIds;
+};
-/* FileIndex entry in bootstrap record */
-typedef struct s_rbsr_findex {
- struct s_rbsr_findex *next;
+/* FileIndex entry in restore bootstrap record */
+struct RBSR_FINDEX {
+ RBSR_FINDEX *next;
int32_t findex;
int32_t findex2;
-} RBSR_FINDEX;
-
-/* Restore bootstrap record -- not the real one, but useful here */
-typedef struct s_rbsr {
- struct s_rbsr *next; /* next JobId */
+};
+
+/*
+ * Restore bootstrap record -- not the real one, but useful here
+ * The restore bsr is a chain of BSR records (linked by next).
+ * Each BSR represents a single JobId, and within it, it
+ * contains a linked list of file indexes for that JobId.
+ * The complete_bsr() routine, will then add all the volumes
+ * on which the Job is stored to the BSR.
+ */
+struct RBSR {
+ RBSR *next; /* next JobId */
uint32_t JobId; /* JobId this bsr */
uint32_t VolSessionId;
uint32_t VolSessionTime;
int VolCount; /* Volume parameter count */
VOL_PARAMS *VolParams; /* Volume, start/end file/blocks */
RBSR_FINDEX *fi; /* File indexes this JobId */
-} RBSR;
+};
-typedef struct s_name_ctx {
+struct NAME_LIST {
char **name; /* list of names */
int num_ids; /* ids stored */
int max_ids; /* size of array */
int num_del; /* number deleted */
int tot_ids; /* total to process */
-} NAME_LIST;
+};
#define MAX_ID_LIST_LEN 1000000
static int unique_name_list_handler(void *ctx, int num_fields, char **row);
static void free_name_list(NAME_LIST *name_list);
static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, JobIds *ji);
+static RBSR *sort_bsr(RBSR *bsr);
/*
if (where) {
Mmsg(&ua->cmd,
"run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\""
- "where=\"%s\"",
+ " where=\"%s\"",
job->hdr.name, ji.ClientName, ji.store?ji.store->hdr.name:"",
working_directory, where);
} else {
FILE *fd;
POOLMEM *fname = get_pool_memory(PM_MESSAGE);
int stat;
- RBSR *nbsr;
Mmsg(&fname, "%s/restore.bsr", working_directory);
fd = fopen(fname, "w+");
free_pool_memory(fname);
return 0;
}
+ /* Sort the bsr chain */
+ bsr = sort_bsr(bsr);
+ /* Write them to file */
write_bsr(ua, bsr, fd);
stat = !ferror(fd);
fclose(fd);
bsendmsg(ua, _("Bootstrap records written to %s\n"), fname);
+
+ /* Tell the user what he will need to mount */
bsendmsg(ua, _("\nThe restore job will require the following Volumes:\n"));
/* Create Unique list of Volumes using prompt list */
start_prompt(ua, "");
- for (nbsr=bsr; nbsr; nbsr=nbsr->next) {
+ for (RBSR *nbsr=bsr; nbsr; nbsr=nbsr->next) {
for (int i=0; i < nbsr->VolCount; i++) {
add_prompt(ua, nbsr->VolParams[i].VolumeName);
}
return stat;
}
+int comp_vol_params(const void *v1, const void *v2)
+{
+ VOL_PARAMS *vol1 = (VOL_PARAMS *)v1;
+ VOL_PARAMS *vol2 = (VOL_PARAMS *)v2;
+
+ if (vol1->FirstIndex < vol2->FirstIndex) {
+ return -1;
+ } else if (vol1->FirstIndex > vol2->FirstIndex) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * First sort the bsr chain, then sort the VolParams
+ */
+static RBSR *sort_bsr(RBSR *bsr)
+{
+ if (!bsr) {
+ return bsr;
+ }
+ /* ****FIXME**** sort the bsr chain */
+ /* Sort the VolParams for each bsr */
+ for (RBSR *nbsr=bsr; nbsr; nbsr=nbsr->next) {
+ if (nbsr->VolCount > 1) {
+ Dmsg1(100, "VolCount=%d\n", nbsr->VolCount);
+ qsort((void *)nbsr->VolParams, nbsr->VolCount, sizeof(VOL_PARAMS),
+ comp_vol_params);
+ }
+ }
+ return bsr;
+}
+
static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd)
{
if (bsr) {
/* Object implementing the Events dialog for Bacula */
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 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 published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA.
*/
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
-// This file is part of the VNC system.
+// This file was part of the VNC system.
//
// The VNC system is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
-// This file is part of the ups system.
+// This file was part of the ups system.
//
// The ups system is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
bacStatus::Show(BOOL show)
{
if (show && !visible) {
- DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_STATUS), NULL,
- (DLGPROC)DialogProc, (LONG)this);
+ DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_STATUS), NULL,
+ (DLGPROC)DialogProc, (LONG)this);
}
}
*
*/
/*
- Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 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 published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA.
*/
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
-// This file is part of the VNC system.
+// This file was part of the VNC system.
//
// The VNC system is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
BSOCK *store_bsock; /* Storage connection socket */
BSOCK *file_bsock; /* File daemon connection socket */
JCR_free_HANDLER *daemon_free_jcr; /* Local free routine */
- int use_count; /* use count */
+ volatile int use_count; /* use count */
POOLMEM *errmsg; /* edited error message */
char Job[MAX_NAME_LENGTH]; /* Unique name of this Job */
uint32_t JobId; /* Director's JobId */
uint64_t JobBytes; /* Number of bytes processed this job */
uint64_t ReadBytes; /* Bytes read -- before compression */
uint32_t Errors; /* Number of non-fatal errors */
- int JobStatus; /* ready, running, blocked, terminated */
+ volatile int JobStatus; /* ready, running, blocked, terminated */
int JobType; /* backup, restore, verify ... */
int JobLevel; /* Job level */
int authenticated; /* set when client authenticated */
pthread_t SD_msg_chan; /* Message channel thread id */
pthread_cond_t term_wait; /* Wait for job termination */
workq_ele_t *work_item; /* Work queue item if scheduled */
- int msg_thread_done; /* Set when Storage message thread terms */
+ volatile int msg_thread_done; /* Set when Storage message thread terms */
BSOCK *ua; /* User agent */
JOB *job; /* Job resource */
STORE *store; /* Storage resource */
FILESET *fileset; /* FileSet resource */
CAT *catalog; /* Catalog resource */
MSGS *messages; /* Default message handler */
- int SDJobStatus; /* Storage Job Status */
- int FDJobStatus; /* File daemon Job Status */
+ volatile int SDJobStatus; /* Storage Job Status */
+ volatile int FDJobStatus; /* File daemon Job Status */
int mode; /* manual/auto run */
B_DB *db; /* database pointer */
uint32_t MediaId; /* DB record IDs associated with this job */
uint32_t StartBlock;
uint32_t EndBlock;
pthread_t heartbeat_id; /* id of heartbeat thread */
- BSOCK *hb_bsock; /* duped SD socket */
+ volatile BSOCK *hb_bsock; /* duped SD socket */
#endif /* FILE_DAEMON */
}
/* Start worker process */
switch (bpipe->worker_pid = fork()) {
- case -1:
+ case -1: /* error */
free(bpipe);
return NULL;
*/
-typedef struct s_bsock {
+struct BSOCK {
uint64_t read_seqno; /* read sequence number */
- uint32_t in_msg_no; /* intput message number */
+ uint32_t in_msg_no; /* input message number */
uint32_t out_msg_no; /* output message number */
int fd; /* socket file descriptor */
int32_t msglen; /* message length */
int port; /* desired port */
- int errors; /* set if errors on socket */
- int suppress_error_msgs; /* set to suppress error messages */
+ volatile int errors; /* set if errors on socket */
+ volatile int suppress_error_msgs; /* set to suppress error messages */
int b_errno; /* bsock errno */
- time_t timer_start; /* time started read/write */
- int timed_out; /* timed out in read/write */
- int timeout; /* time out after this value */
- int terminated; /* set when BNET_TERMINATE arrives */
+ volatile time_t timer_start; /* time started read/write */
+ volatile int timed_out; /* timed out in read/write */
+ volatile int timeout; /* time out after this value */
+ volatile int terminated; /* set when BNET_TERMINATE arrives */
int duped; /* set if duped BSOCK */
POOLMEM *msg; /* message pool buffer */
char *who; /* Name of daemon to which we are talking */
char *host; /* Host name/IP */
POOLMEM *errmsg; /* edited error message (to be implemented) */
RES *res; /* Resource to which we are connected */
- struct s_bsock *next; /* next BSOCK if duped */
+ BSOCK *next; /* next BSOCK if duped */
int spool; /* set for spooling */
FILE *spool_fd; /* spooling file */
JCR *jcr; /* jcr or NULL for error msgs */
-} BSOCK;
+};
/* Signal definitions for use in bnet_sig() */
#define BNET_EOD -1 /* End of data stream, new data may follow */
if ((shellcmd = getenv("SHELL")) == NULL) {
shellcmd = "/bin/sh";
}
- close(1); dup(pfd[1]); /* attach pipes to stdin and stdout */
+#ifdef xxx
+ close(1); dup(pfd[1]); /* attach pipes to stdout and stderr */
close(2); dup(pfd[1]);
for (i = 3; i < 32; i++) /* close everything else */
close(i);
+#endif
+ close(pfd[0]); /* close stdin */
+ dup2(pfd[1], 1); /* attach to stdout */
+ dup2(pfd[1], 2); /* and stderr */
strcpy(echout, "echo "); /* form echo command */
bstrncat(echout, name, sizeof(echout));
execl(shellcmd, shellcmd, "-c", echout, NULL); /* give to shell */
default: /* parent */
/* read output from child */
echout[0] = 0;
- i = read(pfd[0], echout, sizeof echout);
+ do {
+ i = read(pfd[0], echout, sizeof echout);
+ } while (i == -1 && errno == EINTR);
+
if (i > 0) {
echout[--i] = 0; /* set end of string */
/* look for first line. */
block.c dev.c \
device.c dircmd.c fd_cmds.c job.c \
label.c match_bsr.c parse_bsr.c \
- read.c record.c stored_conf.c mount.c
+ read.c record.c status.c stored_conf.c mount.c
SVROBJS = stored.o autochanger.o acquire.o append.o \
askdir.o authenticate.o \
block.o dev.o \
device.o dircmd.o fd_cmds.o job.o \
label.o match_bsr.o mount.o parse_bsr.o \
- read.o record.o stored_conf.o
+ read.o record.o status.o stored_conf.o
# btape
TAPESRCS = btape.c block.c butil.c dev.c device.c label.c \
wlen, stat, dev->dev_errno, strerror(dev->dev_errno));
if (stat == -1) {
- Jmsg2(jcr, M_ERROR, 0, _("Write error on device %s. ERR=%s.\n"),
+ Jmsg(jcr, M_ERROR, 0, _("Write error on device %s. ERR=%s.\n"),
dev->dev_name, strerror(dev->dev_errno));
} else {
Jmsg3(jcr, M_INFO, 0, _("End of media on device %s. Write of %u bytes got %d.\n"),
if (dev->state & (ST_EOT | ST_WEOT)) {
stat |= BMT_EOD;
- Dmsg0(-20, " EOD");
+ Dmsg0(-20, " EOD-");
}
if (dev->state & ST_EOF) {
stat |= BMT_EOF;
}
if (GMT_EOD(mt_stat.mt_gstat)) {
stat |= BMT_EOD;
- Dmsg0(-20, " EOD");
+ Dmsg0(-20, " EOD+");
}
if (GMT_WR_PROT(mt_stat.mt_gstat)) {
stat |= BMT_WR_PROT;
}
-/* To make following two functions more readable */
-
-#define attached_jcrs ((JCR *)(dev->attached_jcrs))
void attach_jcr_to_device(DEVICE *dev, JCR *jcr)
{
- jcr->prev_dev = NULL;
- jcr->next_dev = attached_jcrs;
- if (attached_jcrs) {
- attached_jcrs->prev_dev = jcr;
+ jcr->prev_dev = (JCR *)NULL;
+ jcr->next_dev = dev->attached_jcrs;
+ if (dev->attached_jcrs) {
+ dev->attached_jcrs->prev_dev = jcr;
}
- attached_jcrs = jcr;
+ dev->attached_jcrs = jcr;
Dmsg1(100, "Attached Job %s\n", jcr->Job);
}
void detach_jcr_from_device(DEVICE *dev, JCR *jcr)
{
if (!jcr->prev_dev) {
- attached_jcrs = jcr->next_dev;
+ dev->attached_jcrs = jcr->next_dev;
} else {
jcr->prev_dev->next_dev = jcr->next_dev;
}
JCR *next_attached_jcr(DEVICE *dev, JCR *jcr)
{
- if (jcr == NULL) {
- return attached_jcrs;
+ if (jcr == (JCR *)NULL) {
+ return dev->attached_jcrs;
}
return jcr->next_dev;
}
int dev_blocked; /* state */
} bsteal_lock_t;
+struct DEVRES; /* Device resource defined in stored_conf.h */
/* Device structure definition */
-typedef struct s_device {
- struct s_device *next; /* pointer to next open device */
- struct s_device *prev; /* pointer to prev open device */
- void *attached_jcrs; /* attached JCR list */
+struct DEVICE {
+ DEVICE *next; /* pointer to next open device */
+ DEVICE *prev; /* pointer to prev open device */
+ JCR *attached_jcrs; /* attached JCR list */
pthread_mutex_t mutex; /* access control */
pthread_cond_t wait; /* thread wait variable */
pthread_cond_t wait_next_vol; /* wait for tape to be mounted */
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 */
- void *device; /* pointer to Device Resource */
+ DEVRES *device; /* pointer to Device Resource */
btimer_id tid; /* timer id */
VOLUME_CAT_INFO VolCatInfo; /* Volume Catalog Information */
VOLUME_LABEL VolHdr; /* Actual volume label */
-} DEVICE;
+};
-
-
-#ifdef SunOS
-#define DEFAULT_TAPE_DRIVE "/dev/rmt/0cbn"
-#endif
-#ifdef AIX
-#define DEFAULT_TAPE_DRIVE "/dev/rmt0.1"
-#endif
-#ifdef SGI
-#define DEFAULT_TAPE_DRIVE "/dev/tps0d4nr"
-#endif
-#ifdef Linux
-#define DEFAULT_TAPE_DRIVE "/dev/nst0"
-#endif
-#ifdef OSF
-#define DEFAULT_TAPE_DRIVE "/dev/nrmt0"
-#endif
-#ifdef HPUX
-#define DEFAULT_TAPE_DRIVE "/dev/rmt/0hnb"
-#endif
-#ifdef FreeBSD
-#define DEFAULT_TAPE_DRIVE "/dev/nrst0"
-#endif
-
-/* Default default */
-#ifndef DEFAULT_TAPE_DRIVE
-#define DEFAULT_TAPE_DRIVE "/dev/nst0"
-#endif
-
/* Get some definition of function to position
* to the end of the medium in MTEOM. System
* dependent. Arrgggg!
/* Imported functions */
extern void terminate_child();
extern int job_cmd(JCR *jcr);
+extern int status_cmd(JCR *sjcr);
/* Forward referenced functions */
static int label_cmd(JCR *jcr);
static int cancel_cmd(JCR *cjcr);
static int mount_cmd(JCR *jcr);
static int unmount_cmd(JCR *jcr);
-static int status_cmd(JCR *sjcr);
static int autochanger_cmd(JCR *sjcr);
static int do_label(JCR *jcr, int relabel);
static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
char *newname, char *poolname,
int Slot, int relabel);
-static void send_blocked_status(JCR *jcr, DEVICE *dev);
struct s_cmds {
char *cmd;
return 1;
}
-/*
- * Status command from Director
- */
-static int status_cmd(JCR *jcr)
-{
- DEVRES *device;
- DEVICE *dev;
- int found, bps, sec, bpb;
- BSOCK *user = jcr->dir_bsock;
- char dt[MAX_TIME_LENGTH];
- char b1[30], b2[30], b3[30];
-
- bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ")\n", my_name);
- bstrftime(dt, sizeof(dt), daemon_start_time);
- bnet_fsend(user, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs,
- last_job.NumJobs == 1 ? "" : "s");
- if (last_job.NumJobs > 0) {
- char termstat[30];
-
- bstrftime(dt, sizeof(dt), last_job.end_time);
- bnet_fsend(user, _("Last Job %s finished at %s\n"), last_job.Job, dt);
-
- jobstatus_to_ascii(last_job.JobStatus, termstat, sizeof(termstat));
- bnet_fsend(user, _(" Files=%s Bytes=%s Termination Status=%s\n"),
- edit_uint64_with_commas(last_job.JobFiles, b1),
- edit_uint64_with_commas(last_job.JobBytes, b2),
- termstat);
- }
-
- LockRes();
- for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
- for (dev=device->dev; dev; dev=dev->next) {
- if (dev->state & ST_OPENED) {
- if (dev->state & ST_LABEL) {
- bnet_fsend(user, _("Device %s is mounted with Volume \"%s\"\n"),
- dev_name(dev), dev->VolHdr.VolName);
- } else {
- bnet_fsend(user, _("Device %s open but no Bacula volume is mounted.\n"), dev_name(dev));
- }
- send_blocked_status(jcr, dev);
- if (dev->state & ST_APPEND) {
- bpb = dev->VolCatInfo.VolCatBlocks;
- if (bpb <= 0) {
- bpb = 1;
- }
- bpb = dev->VolCatInfo.VolCatBytes / bpb;
- bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"),
- edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
- edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
- edit_uint64_with_commas(bpb, b3));
- } else { /* reading */
- bpb = dev->VolCatInfo.VolCatReads;
- if (bpb <= 0) {
- bpb = 1;
- }
- bpb = dev->VolCatInfo.VolCatRBytes / bpb;
- bnet_fsend(user, _(" Total Bytes Read=%s Blocks Read=%s Bytes/block=%s\n"),
- edit_uint64_with_commas(dev->VolCatInfo.VolCatRBytes, b1),
- edit_uint64_with_commas(dev->VolCatInfo.VolCatReads, b2),
- edit_uint64_with_commas(bpb, b3));
- }
- bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"),
- edit_uint64_with_commas(dev->file, b1),
- edit_uint64_with_commas(dev->block_num, b2));
-
- } else {
- bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev));
- send_blocked_status(jcr, dev);
- }
- }
- }
- UnlockRes();
-
- found = 0;
- lock_jcr_chain();
- /* NOTE, we reuse a calling argument jcr. Be warned! */
- for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
- if (jcr->JobStatus == JS_WaitFD) {
- bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
- job_type_to_str(jcr->JobType), jcr->Job);
- }
- if (jcr->device) {
- bnet_fsend(user, _("%s %s job %s is using device %s volume %s\n"),
- job_level_to_str(jcr->JobLevel),
- job_type_to_str(jcr->JobType),
- jcr->Job, jcr->device->device_name,
- jcr->VolumeName);
- sec = time(NULL) - jcr->run_time;
- if (sec <= 0) {
- sec = 1;
- }
- bps = jcr->JobBytes / sec;
- bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
- edit_uint64_with_commas(jcr->JobFiles, b1),
- edit_uint64_with_commas(jcr->JobBytes, b2),
- edit_uint64_with_commas(bps, b3));
- found = 1;
-#ifdef DEBUG
- if (jcr->file_bsock) {
- bnet_fsend(user, " FDReadSeqNo=%" lld " fd=%d\n",
- jcr->file_bsock->read_seqno, jcr->file_bsock->fd);
- } else {
- bnet_fsend(user, " FDSocket closed\n");
- }
-#endif
- }
- free_locked_jcr(jcr);
- }
- unlock_jcr_chain();
- if (!found) {
- bnet_fsend(user, _("No jobs running.\n"));
- }
-
-#ifdef full_status
- bnet_fsend(user, "\n\n");
- dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user);
-#endif
- bnet_fsend(user, "====\n");
-
- bnet_sig(user, BNET_EOD);
- return 1;
-}
-
-static void send_blocked_status(JCR *jcr, DEVICE *dev)
-{
- BSOCK *user = jcr->dir_bsock;
-
- switch (dev->dev_blocked) {
- case BST_UNMOUNTED:
- bnet_fsend(user, _(" Device is BLOCKED. User unmounted.\n"));
- break;
- case BST_UNMOUNTED_WAITING_FOR_SYSOP:
- bnet_fsend(user, _(" Device is BLOCKED. User unmounted during wait for media/mount.\n"));
- break;
- case BST_WAITING_FOR_SYSOP:
- if (jcr->JobStatus == JS_WaitMount) {
- bnet_fsend(user, _(" Device is BLOCKED waiting for mount.\n"));
- } else {
- bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n"));
- }
- break;
- case BST_DOING_ACQUIRE:
- bnet_fsend(user, _(" Device is being initialized.\n"));
- break;
- case BST_WRITING_LABEL:
- bnet_fsend(user, _(" Device is blocked labeling a Volume.\n"));
- break;
- default:
- break;
- }
-}
/*
* Autochanger command from Director
dev->VolCatInfo.VolCatFiles = 0;
dev->VolCatInfo.VolCatErrors = 0;
dev->VolCatInfo.VolCatBlocks = 0;
+ dev->VolCatInfo.VolCatRBytes = 0;
if (recycle) {
dev->VolCatInfo.VolCatMounts++;
dev->VolCatInfo.VolCatRecycles++;
--- /dev/null
+/*
+ * This file handles the status command
+ *
+ * Kern Sibbald, May MMIII
+ *
+ * Version $Id$
+ *
+ */
+/*
+ Copyright (C) 2000-2003 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
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "stored.h"
+
+/* Exported variables */
+
+/* Imported variables */
+extern BSOCK *filed_chan;
+extern int r_first, r_last;
+extern struct s_res resources[];
+extern char my_name[];
+extern time_t daemon_start_time;
+extern struct s_last_job last_job;
+
+/* Static variables */
+
+
+/* Forward referenced functions */
+static void send_blocked_status(JCR *jcr, DEVICE *dev);
+
+
+/*
+ * Status command from Director
+ */
+int status_cmd(JCR *jcr)
+{
+ DEVRES *device;
+ DEVICE *dev;
+ int found, bps, sec, bpb;
+ BSOCK *user = jcr->dir_bsock;
+ char dt[MAX_TIME_LENGTH];
+ char b1[30], b2[30], b3[30];
+
+ bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ")\n", my_name);
+ bstrftime(dt, sizeof(dt), daemon_start_time);
+ bnet_fsend(user, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs,
+ last_job.NumJobs == 1 ? "" : "s");
+ if (last_job.NumJobs > 0) {
+ char termstat[30];
+
+ bstrftime(dt, sizeof(dt), last_job.end_time);
+ bnet_fsend(user, _("Last Job %s finished at %s\n"), last_job.Job, dt);
+
+ jobstatus_to_ascii(last_job.JobStatus, termstat, sizeof(termstat));
+ bnet_fsend(user, _(" Files=%s Bytes=%s Termination Status=%s\n"),
+ edit_uint64_with_commas(last_job.JobFiles, b1),
+ edit_uint64_with_commas(last_job.JobBytes, b2),
+ termstat);
+ }
+
+ LockRes();
+ for (device=NULL; (device=(DEVRES *)GetNextRes(R_DEVICE, (RES *)device)); ) {
+ for (dev=device->dev; dev; dev=dev->next) {
+ if (dev->state & ST_OPENED) {
+ if (dev->state & ST_LABEL) {
+ bnet_fsend(user, _("Device %s is mounted with Volume \"%s\"\n"),
+ dev_name(dev), dev->VolHdr.VolName);
+ } else {
+ bnet_fsend(user, _("Device %s open but no Bacula volume is mounted.\n"), dev_name(dev));
+ }
+ send_blocked_status(jcr, dev);
+ if (dev->state & ST_APPEND) {
+ bpb = dev->VolCatInfo.VolCatBlocks;
+ if (bpb <= 0) {
+ bpb = 1;
+ }
+ bpb = dev->VolCatInfo.VolCatBytes / bpb;
+ bnet_fsend(user, _(" Total Bytes=%s Blocks=%s Bytes/block=%s\n"),
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
+ edit_uint64_with_commas(bpb, b3));
+ } else { /* reading */
+ bpb = dev->VolCatInfo.VolCatReads;
+ if (bpb <= 0) {
+ bpb = 1;
+ }
+ bpb = dev->VolCatInfo.VolCatRBytes / bpb;
+ bnet_fsend(user, _(" Total Bytes Read=%s Blocks Read=%s Bytes/block=%s\n"),
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatRBytes, b1),
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatReads, b2),
+ edit_uint64_with_commas(bpb, b3));
+ }
+ bnet_fsend(user, _(" Positioned at File=%s Block=%s\n"),
+ edit_uint64_with_commas(dev->file, b1),
+ edit_uint64_with_commas(dev->block_num, b2));
+
+ } else {
+ bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev));
+ send_blocked_status(jcr, dev);
+ }
+ }
+ }
+ UnlockRes();
+
+ found = 0;
+ lock_jcr_chain();
+ /* NOTE, we reuse a calling argument jcr. Be warned! */
+ for (jcr=NULL; (jcr=get_next_jcr(jcr)); ) {
+ if (jcr->JobStatus == JS_WaitFD) {
+ bnet_fsend(user, _("%s Job %s waiting for Client connection.\n"),
+ job_type_to_str(jcr->JobType), jcr->Job);
+ }
+ if (jcr->device) {
+ bnet_fsend(user, _("%s %s job %s is using device %s volume %s\n"),
+ job_level_to_str(jcr->JobLevel),
+ job_type_to_str(jcr->JobType),
+ jcr->Job, jcr->device->device_name,
+ jcr->VolumeName);
+ sec = time(NULL) - jcr->run_time;
+ if (sec <= 0) {
+ sec = 1;
+ }
+ bps = jcr->JobBytes / sec;
+ bnet_fsend(user, _(" Files=%s Bytes=%s Bytes/sec=%s\n"),
+ edit_uint64_with_commas(jcr->JobFiles, b1),
+ edit_uint64_with_commas(jcr->JobBytes, b2),
+ edit_uint64_with_commas(bps, b3));
+ found = 1;
+#ifdef DEBUG
+ if (jcr->file_bsock) {
+ bnet_fsend(user, " FDReadSeqNo=%s in_msg=%u out_msg=%d fd=%d\n",
+ edit_uint64_with_commas(jcr->file_bsock->read_seqno, b1),
+ jcr->file_bsock->in_msg_no, jcr->file_bsock->out_msg_no,
+ jcr->file_bsock->fd);
+ } else {
+ bnet_fsend(user, " FDSocket closed\n");
+ }
+#endif
+ }
+ free_locked_jcr(jcr);
+ }
+ unlock_jcr_chain();
+ if (!found) {
+ bnet_fsend(user, _("No jobs running.\n"));
+ }
+
+#ifdef full_status
+ bnet_fsend(user, "\n\n");
+ dump_resource(R_DEVICE, resources[R_DEVICE-r_first].res_head, sendit, user);
+#endif
+ bnet_fsend(user, "====\n");
+
+ bnet_sig(user, BNET_EOD);
+ return 1;
+}
+
+static void send_blocked_status(JCR *jcr, DEVICE *dev)
+{
+ BSOCK *user = jcr->dir_bsock;
+
+ switch (dev->dev_blocked) {
+ case BST_UNMOUNTED:
+ bnet_fsend(user, _(" Device is BLOCKED. User unmounted.\n"));
+ break;
+ case BST_UNMOUNTED_WAITING_FOR_SYSOP:
+ bnet_fsend(user, _(" Device is BLOCKED. User unmounted during wait for media/mount.\n"));
+ break;
+ case BST_WAITING_FOR_SYSOP:
+ if (jcr->JobStatus == JS_WaitMount) {
+ bnet_fsend(user, _(" Device is BLOCKED waiting for mount.\n"));
+ } else {
+ bnet_fsend(user, _(" Device is BLOCKED waiting for appendable media.\n"));
+ }
+ break;
+ case BST_DOING_ACQUIRE:
+ bnet_fsend(user, _(" Device is being initialized.\n"));
+ break;
+ case BST_WRITING_LABEL:
+ bnet_fsend(user, _(" Device is blocked labeling a Volume.\n"));
+ break;
+ default:
+ break;
+}
+}
#define R_BACKUP 3024
/* Definition of the contents of each Resource */
-struct s_res_dir {
+struct DIRRES {
RES hdr;
char *password; /* Director password */
char *address; /* Director IP address or zero */
int enable_ssl; /* Use SSL with this Director */
};
-typedef struct s_res_dir DIRRES;
/* Storage daemon "global" definitions */
typedef struct s_res_store STORES;
/* Device specific definitions */
-struct s_res_dev {
+struct DEVRES {
RES hdr;
char *media_type; /* User assigned media type */
int64_t volume_capacity; /* advisory capacity */
DEVICE *dev; /* Pointer to phyical dev -- set at runtime */
};
-typedef struct s_res_dev DEVRES;
-
-union u_res {
- struct s_res_dir res_dir;
- struct s_res_store res_store;
- struct s_res_dev res_dev;
- struct s_res_msgs res_msgs;
- RES hdr;
+
+union URES {
+ DIRRES res_dir;
+ STORES res_store;
+ DEVRES res_dev;
+ MSGS res_msgs;
+ RES hdr;
};
-typedef union u_res URES;
/* */
#define VERSION "1.31"
#define VSTRING "1"
-#define BDATE "22 May 2003"
-#define LSMDATE "22May03"
+#define BDATE "23 May 2003"
+#define LSMDATE "23May03"
/* Debug flags */
#define DEBUG 1