X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fbscan.c;h=fde0ba1ff06a960b1e9203d3e768e0a55c11207a;hb=b58f32ee0c8cce5b5f7af1416966b8bd2b3ccb6d;hp=5cc8781e4496cdd83e2769cd520a670c16f73919;hpb=ee5b1e9ee0ad5e91e5085d1af5bb38c4697a0496;p=bacula%2Fbacula diff --git a/bacula/src/stored/bscan.c b/bacula/src/stored/bscan.c index 5cc8781e44..fde0ba1ff0 100644 --- a/bacula/src/stored/bscan.c +++ b/bacula/src/stored/bscan.c @@ -1,3 +1,30 @@ +/* + Bacula® - The Network Backup Solution + + Copyright (C) 2001-2008 Free Software Foundation Europe e.V. + + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation and included + in the file LICENSE. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ /* * * Program to scan a Bacula Volume and compare it with @@ -9,20 +36,6 @@ * * Version $Id$ */ -/* - Copyright (C) 2001-2006 Kern Sibbald - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - version 2 as amended with additional clauses defined in the - file LICENSE in the main source directory. - - 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 - the file LICENSE for additional details. - - */ #include "bacula.h" #include "stored.h" @@ -69,10 +82,12 @@ static ATTR *attr; static time_t lasttime = 0; +static const char *db_driver = "NULL"; static const char *db_name = "bacula"; static const char *db_user = "bacula"; static const char *db_password = ""; static const char *db_host = NULL; +static int db_port = 0; static const char *wd = NULL; static bool update_db = false; static bool update_vol_info = false; @@ -98,17 +113,20 @@ pthread_cond_t wait_device_release = PTHREAD_COND_INITIALIZER; static void usage() { fprintf(stderr, _( -"Copyright (C) 2001-%s Kern Sibbald.\n" +PROG_COPYRIGHT "\nVersion: %s (%s)\n\n" "Usage: bscan [ options ] \n" " -b bootstrap specify a bootstrap file\n" " -c specify configuration file\n" -" -d set debug level to nn\n" +" -d set debug level to \n" +" -dt print timestamp in debug output\n" " -m update media info in database\n" +" -D specify the driver database name (default NULL)\n" " -n specify the database name (default bacula)\n" " -u specify database user name (default bacula)\n" -" -P specify database password (default none)\n" " -h specify database host (default NULL)\n" +" -t specify database port (default 0)\n" " -p proceed inspite of I/O errors\n" " -r list records\n" " -s synchronize or store in database\n" @@ -116,7 +134,7 @@ static void usage() " -v verbose\n" " -V specify Volume names (separated by |)\n" " -w specify working directory (default from conf file)\n" -" -? print this message\n\n"), BYEAR, VERSION, BDATE); +" -? print this message\n\n"), 2001, VERSION, BDATE); exit(1); } @@ -134,8 +152,9 @@ int main (int argc, char *argv[]) my_name_is(argc, argv, "bscan"); init_msg(NULL, NULL); + OSDependentInit(); - while ((ch = getopt(argc, argv, "b:c:d:h:mn:pP:rsSu:vV:w:?")) != -1) { + while ((ch = getopt(argc, argv, "b:c:dD:h:p:mn:pP:rsSt:u:vV:w:?")) != -1) { switch (ch) { case 'S' : showProgress = true; @@ -151,15 +170,28 @@ int main (int argc, char *argv[]) configfile = bstrdup(optarg); break; + case 'D': + db_driver = optarg; + break; + case 'd': /* debug level */ - debug_level = atoi(optarg); - if (debug_level <= 0) - debug_level = 1; + if (*optarg == 't') { + dbg_timestamp = true; + } else { + debug_level = atoi(optarg); + if (debug_level <= 0) { + debug_level = 1; + } + } break; case 'h': db_host = optarg; break; + + case 't': + db_port = atoi(optarg); + break; case 'm': update_vol_info = true; @@ -256,14 +288,14 @@ int main (int argc, char *argv[]) if (showProgress) { char ed1[50]; struct stat sb; - fstat(dev->fd, &sb); + fstat(dev->fd(), &sb); currentVolumeSize = sb.st_size; Pmsg1(000, _("First Volume Size = %sn"), edit_uint64(currentVolumeSize, ed1)); } - if ((db=db_init_database(NULL, db_name, db_user, db_password, - db_host, 0, NULL, 0)) == NULL) { + if ((db=db_init(NULL, db_driver, db_name, db_user, db_password, + db_host, db_port, NULL, 0)) == NULL) { Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n")); } if (!db_open_database(NULL, db)) { @@ -278,8 +310,7 @@ int main (int argc, char *argv[]) if (update_db) { printf("Records added or updated in the catalog:\n%7d Media\n%7d Pool\n%7d Job\n%7d File\n", num_media, num_pools, num_jobs, num_files); - } - else { + } else { printf("Records would have been added or updated in the catalog:\n%7d Media\n%7d Pool\n%7d Job\n%7d File\n", num_media, num_pools, num_jobs, num_files); } @@ -301,25 +332,27 @@ static bool bscan_mount_next_read_volume(DCR *dcr) Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName); foreach_dlist(mdcr, dev->attached_dcrs) { JCR *mjcr = mdcr->jcr; + Dmsg1(000, "========== JobId=%u ========\n", mjcr->JobId); if (mjcr->JobId == 0) { continue; } if (verbose) { Pmsg1(000, _("Create JobMedia for Job %s\n"), mjcr->Job); } - if (dev->is_tape()) { - mdcr->EndBlock = dcr->EndBlock; - mdcr->EndFile = dcr->EndFile; -// } else { -// mdcr->EndBlock = (uint32_t)dcr->file_addr; -// mdcr->EndFile = (uint32_t)(dcr->file_addr >> 32); - } + mdcr->StartBlock = dcr->StartBlock; + mdcr->StartFile = dcr->StartFile; + mdcr->EndBlock = dcr->EndBlock; + mdcr->EndFile = dcr->EndFile; + mdcr->VolMediaId = dcr->VolMediaId; mjcr->read_dcr->VolLastIndex = dcr->VolLastIndex; if (!create_jobmedia_record(db, mjcr)) { Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"), dev->VolCatInfo.VolCatName, mjcr->Job); } } + + update_media_record(db, &mr); + /* Now let common read routine get up next tape. Note, * we call mount_next... with bscan's jcr because that is where we * have the Volume list, but we get attached. @@ -329,7 +362,7 @@ static bool bscan_mount_next_read_volume(DCR *dcr) if (showProgress) { char ed1[50]; struct stat sb; - fstat(dev->fd, &sb); + fstat(dev->fd(), &sb); currentVolumeSize = sb.st_size; Pmsg1(000, _("First Volume Size = %sn"), edit_uint64(currentVolumeSize, ed1)); @@ -339,7 +372,7 @@ static bool bscan_mount_next_read_volume(DCR *dcr) static void do_scan() { - attr = new_attr(); + attr = new_attr(bjcr); memset(&ar, 0, sizeof(ar)); memset(&pr, 0, sizeof(pr)); @@ -352,6 +385,9 @@ static void do_scan() read_records(bjcr->read_dcr, record_cb, bscan_mount_next_read_volume); + if (update_db) { + db_write_batch_file_records(bjcr); /* used by bulk batch file insert */ + } free_attr(attr); } @@ -458,6 +494,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) dcr->VolFirstIndex = dcr->FileIndex = 0; dcr->StartBlock = dcr->EndBlock = 0; dcr->StartFile = dcr->EndFile = 0; + dcr->VolMediaId = 0; } Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName); @@ -498,20 +535,6 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) update_db = save_update_db; jr.PoolId = pr.PoolId; -#ifdef xxx - /* Set start positions into JCR */ - if (dev->is_tape()) { - /* - * Note, we have already advanced past current block, - * so the correct number is block_num - 1 - */ - dcr->StartBlock = dev->block_num - 1; - dcr->StartFile = dev->file; - } else { - dcr->StartBlock = (uint32_t)dev->file_addr; - dcr->StartFile = (uint32_t)(dev->file_addr >> 32); - } -#endif mjcr->start_time = jr.StartTime; mjcr->JobLevel = jr.JobLevel; @@ -596,7 +619,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) jr.VolSessionTime = mjcr->VolSessionTime; jr.JobTDate = (utime_t)mjcr->start_time; jr.ClientId = mjcr->ClientId; - if (!db_update_job_end_record(bjcr, db, &jr)) { + if (!db_update_job_end_record(bjcr, db, &jr, false)) { Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db)); } mjcr->read_dcr = NULL; @@ -765,8 +788,8 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec) } break; - case STREAM_UNIX_ATTRIBUTES_ACCESS_ACL: /* Standard ACL attributes on UNIX */ - case STREAM_UNIX_ATTRIBUTES_DEFAULT_ACL: /* Default ACL attributes on UNIX */ + case STREAM_UNIX_ACCESS_ACL: /* Standard ACL attributes on UNIX */ + case STREAM_UNIX_DEFAULT_ACL: /* Default ACL attributes on UNIX */ /* Ignore Unix attributes */ break; @@ -822,7 +845,11 @@ static int create_file_attributes_record(B_DB *db, JCR *mjcr, ar.ClientId = mjcr->ClientId; ar.JobId = mjcr->JobId; ar.Stream = rec->Stream; - ar.FileIndex = rec->FileIndex; + if (type == FT_DELETED) { + ar.FileIndex = 0; + } else { + ar.FileIndex = rec->FileIndex; + } ar.attr = ap; if (dcr->VolFirstIndex == 0) { dcr->VolFirstIndex = rec->FileIndex; @@ -873,6 +900,12 @@ static int create_media_record(B_DB *db, MEDIA_DBR *mr, VOLUME_LABEL *vl) mr->LabelDate = mktime(&tm); } lasttime = mr->LabelDate; + if (mr->VolJobs == 0) { + mr->VolJobs = 1; + } + if (mr->VolMounts == 0) { + mr->VolMounts = 1; + } if (!update_db) { return 1; @@ -941,7 +974,16 @@ static int create_pool_record(B_DB *db, POOL_DBR *pr) */ static int create_client_record(B_DB *db, CLIENT_DBR *cr) { + /* + * Note, update_db can temporarily be set false while + * updating the database, so we must ensure that ClientId is non-zero. + */ if (!update_db) { + cr->ClientId = 0; + if (!db_get_client_record(bjcr, db, cr)) { + Pmsg1(0, _("Could not get Client record. ERR=%s\n"), db_strerror(db)); + return 0; + } return 1; } if (!db_create_client_record(bjcr, db, cr)) { @@ -1080,7 +1122,7 @@ static int update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel, return 1; } - if (!db_update_job_end_record(bjcr, db, jr)) { + if (!db_update_job_end_record(bjcr, db, jr, false)) { Pmsg2(0, _("Could not update JobId=%u record. ERR=%s\n"), jr->JobId, db_strerror(db)); free_jcr(mjcr); return 0; @@ -1151,15 +1193,9 @@ static int create_jobmedia_record(B_DB *db, JCR *mjcr) JOBMEDIA_DBR jmr; DCR *dcr = mjcr->read_dcr; - if (dev->is_tape()) { - dcr->EndBlock = dev->EndBlock; - dcr->EndFile = dev->EndFile; -#ifdef needed - } else { - dcr->EndBlock = (uint32_t)dev->file_addr; - dcr->EndFile = (uint32_t)(dev->file_addr >> 32); -#endif - } + dcr->EndBlock = dev->EndBlock; + dcr->EndFile = dev->EndFile; + dcr->VolMediaId = dev->VolCatInfo.VolMediaId; memset(&jmr, 0, sizeof(jmr)); jmr.JobId = mjcr->JobId; @@ -1244,21 +1280,21 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId) jobjcr->VolSessionId = rec->VolSessionId; jobjcr->VolSessionTime = rec->VolSessionTime; jobjcr->ClientId = jr->ClientId; - jobjcr->read_dcr = new_dcr(jobjcr, dev); + jobjcr->dcr = jobjcr->read_dcr = new_dcr(jobjcr, NULL, dev); return jobjcr; } /* Dummies to replace askdir.c */ bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} -bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } +bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } bool dir_create_jobmedia_record(DCR *dcr) { return 1; } bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} bool dir_send_job_status(JCR *jcr) {return 1;} int generate_job_event(JCR *jcr, const char *event) { return 1; } -bool dir_ask_sysop_to_mount_volume(DCR *dcr) +bool dir_ask_sysop_to_mount_volume(DCR *dcr, int /*mode*/) { DEVICE *dev = dcr->dev; Dmsg0(20, "Enter dir_ask_sysop_to_mount_volume\n");