]> git.sur5r.net Git - bacula/bacula/commitdiff
- Add new ua_update.c file and move update_cmd there.
authorKern Sibbald <kern@sibbald.com>
Thu, 10 Mar 2005 16:52:42 +0000 (16:52 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 10 Mar 2005 16:52:42 +0000 (16:52 +0000)
- Modify update slots to obtain actual number of slots.
- Tweak autochanger code to handle new slots request.
- Modify autochanger code to lock/unlock around slots and
  update slots code.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1880 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/kernstodo
bacula/src/dird/Makefile.in
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_label.c
bacula/src/dird/ua_update.c [new file with mode: 0644]
bacula/src/lib/mem_pool.c
bacula/src/lib/watchdog.c
bacula/src/stored/autochanger.c
bacula/src/stored/dircmd.c
bacula/src/stored/protos.h
bacula/src/version.h

index 19c71756fb579a6185eec2a7cf6ef9fc49443e70..8aa0c2348883053c4438e4a2eef9615b9aa19079 100644 (file)
@@ -219,6 +219,8 @@ Why:
     format string. Then I have the tape labeled automatically with weekday
     name in the correct language.
 ==========
+- Make output from status use html table tags for nicely 
+  presenting in a browser.
 - Can one write tapes faster with 8192 byte block sizes?
 - Specify a single directory to restore.
 - Document security problems with the same password for everyone in
index 487913c77e535676c59c921b3dc5fafc9fcc479d..b5c6d9f1b21f01b958364205a49eaed8e5958a91 100644 (file)
@@ -39,7 +39,7 @@ SVRSRCS = dird.c admin.c authenticate.c \
          ua_input.c ua_label.c ua_output.c ua_prune.c \
          ua_purge.c ua_restore.c ua_run.c \
          ua_select.c ua_server.c \
-         ua_status.c ua_tree.c verify.c
+         ua_status.c ua_tree.c ua_update.c verify.c
 SVROBJS = dird.o admin.o authenticate.o \
          autoprune.o backup.o bsr.o \
          catreq.o dird_conf.o expand.o \
@@ -54,7 +54,7 @@ SVROBJS = dird.o admin.o authenticate.o \
          ua_input.o ua_label.o ua_output.o ua_prune.o \
          ua_purge.o ua_restore.o ua_run.o \
          ua_select.o ua_server.o \
-         ua_status.o ua_tree.o verify.o
+         ua_status.o ua_tree.o ua_update.o verify.o
 
 # these are the objects that are changed by the .configure process
 EXTRAOBJS = @OBJLIST@
index 13e19c9478a74278f5626efa1c50ac1c6f55161b..d0844f9d101b46320e0af468df4d87425627aec1 100644 (file)
@@ -40,8 +40,6 @@ extern char my_name[];
 extern jobq_t job_queue;             /* job queue */
 
 
-extern char *list_pool;
-
 /* Imported functions */
 extern int status_cmd(UAContext *ua, const char *cmd);
 extern int list_cmd(UAContext *ua, const char *cmd);
@@ -58,7 +56,7 @@ extern int purgecmd(UAContext *ua, const char *cmd);
 extern int restore_cmd(UAContext *ua, const char *cmd);
 extern int label_cmd(UAContext *ua, const char *cmd);
 extern int relabel_cmd(UAContext *ua, const char *cmd);
-extern int update_slots(UAContext *ua);  /* ua_label.c */
+extern int update_cmd(UAContext *ua, const char *cmd);
 
 /* Forward referenced functions */
 static int add_cmd(UAContext *ua, const char *cmd);
@@ -76,14 +74,11 @@ static int version_cmd(UAContext *ua, const char *cmd);
 static int automount_cmd(UAContext *ua, const char *cmd);
 static int time_cmd(UAContext *ua, const char *cmd);
 static int reload_cmd(UAContext *ua, const char *cmd);
-static int update_volume(UAContext *ua);
-static int update_pool(UAContext *ua);
 static int delete_volume(UAContext *ua);
 static int delete_pool(UAContext *ua);
 static void delete_job(UAContext *ua);
 static int mount_cmd(UAContext *ua, const char *cmd);
 static int release_cmd(UAContext *ua, const char *cmd);
-static int update_cmd(UAContext *ua, const char *cmd);
 static int wait_cmd(UAContext *ua, const char *cmd);
 static int setip_cmd(UAContext *ua, const char *cmd);
 static int python_cmd(UAContext *ua, const char *cmd);
@@ -462,7 +457,7 @@ static int cancel_cmd(UAContext *ua, const char *cmd)
  *   depending on if we are creating the Pool or we are
  *   simply bringing it into agreement with the resource (updage).
  */
-static void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op)
+void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op)
 {
    bstrncpy(pr->PoolType, pool->pool_type, sizeof(pr->PoolType));
    if (op == POOL_OP_CREATE) {
@@ -620,607 +615,6 @@ get_out:
 }
 
 
-/*
- * Update a Pool Record in the database.
- *  It is always updated from the Resource record.
- *
- *    update pool=<pool-name>
- *        updates pool from Pool resource
- *    update media pool=<pool-name> volume=<volume-name>
- *        changes pool info for volume
- *    update slots [scan=...]
- *        updates autochanger slots
- */
-static int update_cmd(UAContext *ua, const char *cmd)
-{
-   static const char *kw[] = {
-      N_("media"),  /* 0 */
-      N_("volume"), /* 1 */
-      N_("pool"),   /* 2 */
-      N_("slots"),  /* 3 */
-      NULL};
-
-   if (!open_db(ua)) {
-      return 1;
-   }
-
-   switch (find_arg_keyword(ua, kw)) {
-   case 0:
-   case 1:
-      update_volume(ua);
-      return 1;
-   case 2:
-      update_pool(ua);
-      return 1;
-   case 3:
-      update_slots(ua);
-      return 1;
-   default:
-      break;
-   }
-
-   start_prompt(ua, _("Update choice:\n"));
-   add_prompt(ua, _("Volume parameters"));
-   add_prompt(ua, _("Pool from resource"));
-   add_prompt(ua, _("Slots from autochanger"));
-   switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
-   case 0:
-      update_volume(ua);
-      break;
-   case 1:
-      update_pool(ua);
-      break;
-   case 2:
-      update_slots(ua);
-      break;
-   default:
-      break;
-   }
-   return 1;
-}
-
-static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
-{
-   POOLMEM *query = get_pool_memory(PM_MESSAGE);
-   const char *kw[] = {
-      "Append",
-      "Archive",
-      "Disabled",
-      "Full",
-      "Used",
-      "Cleaning",
-      "Recycle",
-      "Read-Only",
-      NULL};
-   bool found = false;
-   int i;
-
-   for (i=0; kw[i]; i++) {
-      if (strcasecmp(val, kw[i]) == 0) {
-        found = true;
-        break;
-      }
-   }
-   if (!found) {
-      bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
-   } else {
-      char ed1[50];
-      bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
-      Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
-        mr->VolStatus, edit_int64(mr->MediaId,ed1));
-      if (!db_sql_query(ua->db, query, NULL, NULL)) {
-         bsendmsg(ua, "%s", db_strerror(ua->db));
-      } else {
-         bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
-      }
-   }
-   free_pool_memory(query);
-}
-
-static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
-{
-   char ed1[150], ed2[50];
-   POOLMEM *query;
-   if (!duration_to_utime(val, &mr->VolRetention)) {
-      bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
-      return;
-   }
-   query = get_pool_memory(PM_MESSAGE);
-   Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
-      edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
-   if (!db_sql_query(ua->db, query, NULL, NULL)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("New retention period is: %s\n"),
-        edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
-   }
-   free_pool_memory(query);
-}
-
-static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
-{
-   char ed1[150], ed2[50];
-   POOLMEM *query;
-
-   if (!duration_to_utime(val, &mr->VolUseDuration)) {
-      bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
-      return;
-   }
-   query = get_pool_memory(PM_MESSAGE);
-   Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
-      edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
-   if (!db_sql_query(ua->db, query, NULL, NULL)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("New use duration is: %s\n"),
-        edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
-   }
-   free_pool_memory(query);
-}
-
-static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
-{
-   POOLMEM *query = get_pool_memory(PM_MESSAGE);
-   char ed1[50];
-   Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
-      val, edit_int64(mr->MediaId,ed1));
-   if (!db_sql_query(ua->db, query, NULL, NULL)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("New max jobs is: %s\n"), val);
-   }
-   free_pool_memory(query);
-}
-
-static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
-{
-   POOLMEM *query = get_pool_memory(PM_MESSAGE);
-   char ed1[50];
-   Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
-      val, edit_int64(mr->MediaId, ed1));
-   if (!db_sql_query(ua->db, query, NULL, NULL)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("New max files is: %s\n"), val);
-   }
-   free_pool_memory(query);
-}
-
-static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
-{
-   uint64_t maxbytes;
-   char ed1[50], ed2[50];
-   POOLMEM *query;
-
-   if (!size_to_uint64(val, strlen(val), &maxbytes)) {
-      bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
-      return;
-   }
-   query = get_pool_memory(PM_MESSAGE);
-   Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
-      edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
-   if (!db_sql_query(ua->db, query, NULL, NULL)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
-   }
-   free_pool_memory(query);
-}
-
-static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
-{
-   int recycle;
-   char ed1[50];
-   POOLMEM *query;
-   if (strcasecmp(val, _("yes")) == 0) {
-      recycle = 1;
-   } else if (strcasecmp(val, _("no")) == 0) {
-      recycle = 0;
-   } else {
-      bsendmsg(ua, _("Invalid value. It must by yes or no.\n"));
-      return;
-   }
-   query = get_pool_memory(PM_MESSAGE);
-   Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
-      recycle, edit_int64(mr->MediaId, ed1));
-   if (!db_sql_query(ua->db, query, NULL, NULL)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("New Recycle flag is: %s\n"),
-         mr->Recycle==1?_("yes"):_("no"));
-   }
-   free_pool_memory(query);
-}
-
-/* Modify the Pool in which this Volume is located */
-static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
-{
-   POOL_DBR pr;
-   POOLMEM *query;
-   char ed1[50];
-
-   memset(&pr, 0, sizeof(pr));
-   bstrncpy(pr.Name, val, sizeof(pr.Name));
-   if (!get_pool_dbr(ua, &pr)) {
-      return;
-   }
-   mr->PoolId = pr.PoolId;           /* set new PoolId */
-   /*
-    */
-   query = get_pool_memory(PM_MESSAGE);
-   db_lock(ua->db);
-   Mmsg(query, "UPDATE Media SET PoolId=%d WHERE MediaId=%s",
-      mr->PoolId, edit_int64(mr->MediaId, ed1));
-   if (!db_sql_query(ua->db, query, NULL, NULL)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
-      opr->NumVols--;
-      if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
-         bsendmsg(ua, "%s", db_strerror(ua->db));
-      }
-      pr.NumVols++;
-      if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
-         bsendmsg(ua, "%s", db_strerror(ua->db));
-      }
-   }
-   db_unlock(ua->db);
-   free_pool_memory(query);
-}
-
-/*
- * Refresh the Volume information from the Pool record
- */
-static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr)
-{
-   POOL_DBR pr;
-
-   memset(&pr, 0, sizeof(pr));
-   pr.PoolId = mr->PoolId;
-   if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
-       !acl_access_ok(ua, Pool_ACL, pr.Name)) {
-      return;
-   }
-   set_pool_dbr_defaults_in_media_dbr(mr, &pr);
-   if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
-      bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
-        pr.Name);
-   }
-}
-
-/*
- * Refresh the Volume information from the Pool record
- *   for all Volumes
- */
-static void update_all_vols_from_pool(UAContext *ua)
-{
-   POOL_DBR pr;
-   MEDIA_DBR mr;
-
-   memset(&pr, 0, sizeof(pr));
-   memset(&mr, 0, sizeof(mr));
-   if (!get_pool_dbr(ua, &pr)) {
-      return;
-   }
-   set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
-   mr.PoolId = pr.PoolId;
-   if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
-      bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
-   } else {
-      bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
-   }
-}
-
-
-/*
- * Update a media record -- allows you to change the
- *  Volume status. E.g. if you want Bacula to stop
- *  writing on the volume, set it to anything other
- *  than Append.
- */
-static int update_volume(UAContext *ua)
-{
-   MEDIA_DBR mr;
-   POOL_DBR pr;
-   POOLMEM *query;
-   char ed1[130];
-   bool done = false;
-   const char *kw[] = {
-      N_("VolStatus"),                /* 0 */
-      N_("VolRetention"),             /* 1 */
-      N_("VolUse"),                   /* 2 */
-      N_("MaxVolJobs"),               /* 3 */
-      N_("MaxVolFiles"),              /* 4 */
-      N_("MaxVolBytes"),              /* 5 */
-      N_("Recycle"),                  /* 6 */
-      N_("Pool"),                     /* 7 */
-      N_("FromPool"),                 /* 8 */
-      N_("AllFromPool"),              /* 9 */
-      NULL };
-
-   for (int i=0; kw[i]; i++) {
-      int j;
-      POOL_DBR pr;
-      if ((j=find_arg_with_value(ua, kw[i])) > 0) {
-        if (i != 9 && !select_media_dbr(ua, &mr)) {
-           return 0;
-        }
-        switch (i) {
-        case 0:
-           update_volstatus(ua, ua->argv[j], &mr);
-           break;
-        case 1:
-           update_volretention(ua, ua->argv[j], &mr);
-           break;
-        case 2:
-           update_voluseduration(ua, ua->argv[j], &mr);
-           break;
-        case 3:
-           update_volmaxjobs(ua, ua->argv[j], &mr);
-           break;
-        case 4:
-           update_volmaxfiles(ua, ua->argv[j], &mr);
-           break;
-        case 5:
-           update_volmaxbytes(ua, ua->argv[j], &mr);
-           break;
-        case 6:
-           update_volrecycle(ua, ua->argv[j], &mr);
-           break;
-        case 7:
-           memset(&pr, 0, sizeof(POOL_DBR));
-           pr.PoolId = mr.PoolId;
-           if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
-               bsendmsg(ua, "%s", db_strerror(ua->db));
-              break;
-           }
-           update_vol_pool(ua, ua->argv[j], &mr, &pr);
-           break;
-        case 8:
-           update_volfrompool(ua, &mr);
-           return 1;
-        case 9:
-           update_all_vols_from_pool(ua);
-           return 1;
-        }
-        done = true;
-      }
-   }
-
-   for ( ; !done; ) {
-      if (!select_media_dbr(ua, &mr)) {
-        return 0;
-      }
-      bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
-      start_prompt(ua, _("Parameters to modify:\n"));
-      add_prompt(ua, _("Volume Status"));
-      add_prompt(ua, _("Volume Retention Period"));
-      add_prompt(ua, _("Volume Use Duration"));
-      add_prompt(ua, _("Maximum Volume Jobs"));
-      add_prompt(ua, _("Maximum Volume Files"));
-      add_prompt(ua, _("Maximum Volume Bytes"));
-      add_prompt(ua, _("Recycle Flag"));
-      add_prompt(ua, _("Slot"));
-      add_prompt(ua, _("InChanger Flag"));
-      add_prompt(ua, _("Volume Files"));
-      add_prompt(ua, _("Pool"));
-      add_prompt(ua, _("Volume from Pool"));
-      add_prompt(ua, _("All Volumes from Pool"));
-      add_prompt(ua, _("Done"));
-      switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
-      case 0:                        /* Volume Status */
-        /* Modify Volume Status */
-         bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
-         start_prompt(ua, _("Possible Values are:\n"));
-         add_prompt(ua, "Append");      /* Better not translate these as */
-         add_prompt(ua, "Archive");     /* They are known in the database code */
-         add_prompt(ua, "Disabled");
-         add_prompt(ua, "Full");
-         add_prompt(ua, "Used");
-         add_prompt(ua, "Cleaning");
-         if (strcmp(mr.VolStatus, "Purged") == 0) {
-            add_prompt(ua, "Recycle");
-        }
-         add_prompt(ua, "Read-Only");
-         if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
-           return 1;
-        }
-        update_volstatus(ua, ua->cmd, &mr);
-        break;
-      case 1:                        /* Retention */
-         bsendmsg(ua, _("Current retention period is: %s\n"),
-           edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
-         if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
-           return 0;
-        }
-        update_volretention(ua, ua->cmd, &mr);
-        break;
-
-      case 2:                        /* Use Duration */
-         bsendmsg(ua, _("Current use duration is: %s\n"),
-           edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
-         if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
-           return 0;
-        }
-        update_voluseduration(ua, ua->cmd, &mr);
-        break;
-
-      case 3:                        /* Max Jobs */
-         bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
-         if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
-           return 0;
-        }
-        update_volmaxjobs(ua, ua->cmd, &mr);
-        break;
-
-      case 4:                        /* Max Files */
-         bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
-         if (!get_pint(ua, _("Enter new Maximum Files: "))) {
-           return 0;
-        }
-        update_volmaxfiles(ua, ua->cmd, &mr);
-        break;
-
-      case 5:                        /* Max Bytes */
-         bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
-         if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
-           return 0;
-        }
-        update_volmaxbytes(ua, ua->cmd, &mr);
-        break;
-
-
-      case 6:                        /* Recycle */
-         bsendmsg(ua, _("Current recycle flag is: %s\n"),
-            mr.Recycle==1?_("yes"):_("no"));
-         if (!get_yesno(ua, _("Enter new Recycle status: "))) {
-           return 0;
-        }
-        update_volrecycle(ua, ua->cmd, &mr);
-        break;
-
-      case 7:                        /* Slot */
-        int Slot;
-
-        memset(&pr, 0, sizeof(POOL_DBR));
-        pr.PoolId = mr.PoolId;
-        if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-           return 0;
-        }
-         bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
-         if (!get_pint(ua, _("Enter new Slot: "))) {
-           return 0;
-        }
-        Slot = ua->pint32_val;
-        if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
-            bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
-              pr.MaxVols);
-           break;
-        }
-        mr.Slot = Slot;
-        /*
-         * Make sure to use db_update... rather than doing this directly,
-         *   so that any Slot is handled correctly.
-         */
-        if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
-            bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot);
-        }
-        break;
-
-      case 8:                        /* InChanger */
-         bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
-         if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
-           return 0;
-        }
-        mr.InChanger = ua->pint32_val;
-        /*
-         * Make sure to use db_update... rather than doing this directly,
-         *   so that any Slot is handled correctly.
-         */
-        if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
-            bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
-        }
-        break;
-
-
-      case 9:                        /* Volume Files */
-        int32_t VolFiles;
-         bsendmsg(ua, _("Warning changing Volume Files can result\n"
-                        "in loss of data on your Volume\n\n"));
-         bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
-         if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
-           return 0;
-        }
-        VolFiles = ua->pint32_val;
-        if (VolFiles != (int)(mr.VolFiles + 1)) {
-            bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
-            if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
-              break;
-           }
-        }
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
-           VolFiles, edit_int64(mr.MediaId, ed1));
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
-        }
-        free_pool_memory(query);
-        break;
-
-      case 10:                        /* Volume's Pool */
-        memset(&pr, 0, sizeof(POOL_DBR));
-        pr.PoolId = mr.PoolId;
-        if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-           return 0;
-        }
-         bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
-         if (!get_cmd(ua, _("Enter new Pool name: "))) {
-           return 0;
-        }
-        update_vol_pool(ua, ua->cmd, &mr, &pr);
-        return 1;
-
-      case 11:
-        update_volfrompool(ua, &mr);
-        return 1;
-      case 12:
-        update_all_vols_from_pool(ua);
-        return 1;
-      default:                       /* Done or error */
-         bsendmsg(ua, "Selection done.\n");
-        return 1;
-      }
-   }
-   return 1;
-}
-
-/*
- * Update pool record -- pull info from current POOL resource
- */
-static int update_pool(UAContext *ua)
-{
-   POOL_DBR  pr;
-   int id;
-   POOL *pool;
-   POOLMEM *query;
-
-   pool = get_pool_resource(ua);
-   if (!pool) {
-      return 0;
-   }
-
-   memset(&pr, 0, sizeof(pr));
-   bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
-   if (!get_pool_dbr(ua, &pr)) {
-      return 0;
-   }
-
-   set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
-
-   id = db_update_pool_record(ua->jcr, ua->db, &pr);
-   if (id <= 0) {
-      bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
-        id, db_strerror(ua->db));
-   }
-   query = get_pool_memory(PM_MESSAGE);
-   Mmsg(query, list_pool, pr.PoolId);
-   db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
-   free_pool_memory(query);
-   bsendmsg(ua, _("Pool DB record updated from resource.\n"));
-   return 1;
-}
-
-
 static void do_storage_setdebug(UAContext *ua, STORE *store, int level, int trace_flag)
 {
    BSOCK *sd;
index 1fe5dc0647fc0125b9d62567d9acd3ab0e3b8f1e..bea22f84fe075b4cef3e11924832cd3bff5755e9 100644 (file)
@@ -49,6 +49,7 @@ static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr);
 static BSOCK *open_sd_bsock(UAContext *ua);
 static void close_sd_bsock(UAContext *ua);
 static char *get_volume_name_from_SD(UAContext *ua, int Slot);
+static int get_num_slots_from_SD(UAContext *ua);
 
 
 /*
@@ -66,14 +67,12 @@ int relabel_cmd(UAContext *ua, const char *cmd)
    return do_label(ua, cmd, 1);      /* relabel tape */
 }
 
-static int const max_slots = 5000;
-
 static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots)
 {
    int i;
    const char *msg;
 
-   for (int i=0; i<num_slots; i++) {
+   for (int i=0; i <= num_slots; i++) {
       slot_list[i] = 0;
    }
    i = find_arg_with_value(ua, "slots");
@@ -134,13 +133,13 @@ static bool get_user_slot_list(UAContext *ua, char *slot_list, int num_slots)
       }
    } else {
       /* Turn everything on */
-      for (i=0; i<num_slots; i++) {
+      for (i=0; i <= num_slots; i++) {
         slot_list[i] = 1;
       }
    }
 #ifdef xxx_debug
    printf("Slots turned on:\n");
-   for (i=1; i<num_slots; i++) {
+   for (i=1; i <= num_slots; i++) {
       if (slot_list[i]) {
          printf("%d\n", i);
       }
@@ -162,6 +161,8 @@ int update_slots(UAContext *ua)
    MEDIA_DBR mr;
    char *slot_list;
    bool scan;
+   int max_slots;
+
 
    if (!open_db(ua)) {
       return 1;
@@ -174,7 +175,12 @@ int update_slots(UAContext *ua)
 
    scan = find_arg(ua, _("scan")) >= 0;
 
-   slot_list = (char *)malloc(max_slots);
+   max_slots = get_num_slots_from_SD(ua);
+   if (max_slots <= 0) {
+      bsendmsg(ua, _("No slots in changer to scan.\n"));
+      return 1;
+   }
+   slot_list = (char *)malloc(max_slots+1);
    if (!get_user_slot_list(ua, slot_list, max_slots)) {
       free(slot_list);
       return 1;
@@ -189,8 +195,9 @@ int update_slots(UAContext *ua)
 
    /* Walk through the list updating the media records */
    for (vl=vol_list; vl; vl=vl->next) {
-      if (vl->Slot >= max_slots) {
-         bsendmsg(ua, _("Slot %d larger than max %d ignored.\n"));
+      if (vl->Slot > max_slots) {
+         bsendmsg(ua, _("Slot %d larger than max %d ignored.\n"),
+           vl->Slot, max_slots);
         continue;
       }
       /* Check if user wants us to look at this slot */
@@ -252,7 +259,7 @@ int update_slots(UAContext *ua)
    mr.InChanger = 1;
    mr.StorageId = store->StorageId;
    db_lock(ua->db);
-   for (int i=1; i<max_slots; i++) {
+   for (int i=1; i <= max_slots; i++) {
       if (slot_list[i]) {
         mr.Slot = i;
         /* Set InChanger to zero for this Slot */
@@ -448,8 +455,15 @@ static void label_from_barcodes(UAContext *ua)
    vol_list_t *vl, *vol_list = NULL;
    bool media_record_exists;
    char *slot_list;
+   int max_slots;
 
-   slot_list = (char *)malloc(max_slots);
+  
+   max_slots = get_num_slots_from_SD(ua);
+   if (max_slots <= 0) {
+      bsendmsg(ua, _("No slots in changer to scan.\n"));
+      return;
+   }
+   slot_list = (char *)malloc(max_slots+1);
    if (!get_user_slot_list(ua, slot_list, max_slots)) {
       goto bail_out;
    }
@@ -832,6 +846,39 @@ static void free_vol_list(vol_list_t *vol_list)
    }
 }
 
+/*
+ * We get the number of slots in the changer from the SD
+ */
+static int get_num_slots_from_SD(UAContext *ua)
+{
+   STORE *store = ua->jcr->store;
+   char dev_name[MAX_NAME_LENGTH];
+   BSOCK *sd;
+   int slots = 0;
+
+
+   if (!(sd=open_sd_bsock(ua))) {
+      return 0;
+   }
+
+   bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
+   bash_spaces(dev_name);
+   /* Ask for autochanger list of volumes */
+   bnet_fsend(sd, _("autochanger slots %s \n"), dev_name);
+
+   while (bnet_recv(sd) >= 0) {
+      if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) {
+        break;
+      } else {
+         bsendmsg(ua, "%s", sd->msg);
+      }
+   }
+   close_sd_bsock(ua);
+   bsendmsg(ua, _("Device \"%s\" has %d slots.\n"), store->dev_name(), slots);
+   return slots;
+}
+
+
 
 /*
  * Check if this is a cleaning tape by comparing the Volume name
diff --git a/bacula/src/dird/ua_update.c b/bacula/src/dird/ua_update.c
new file mode 100644 (file)
index 0000000..b9a016c
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+ *
+ *   Bacula Director -- Update command processing
+ *     Split from ua_cmds.c March 2005
+ *
+ *     Kern Sibbald, September MM
+ *
+ *   Version $Id$
+ */
+
+/*
+   Copyright (C) 2000-2005 Kern Sibbald
+
+   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 "dird.h"
+
+/* External variables */
+extern char *list_pool;              /* in sql_cmds.c */
+
+/* Imported functions */
+void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
+int update_slots(UAContext *ua);
+
+
+/* Forward referenced functions */
+static int update_volume(UAContext *ua);
+static int update_pool(UAContext *ua);
+
+/*
+ * Update a Pool Record in the database.
+ *  It is always updated from the Resource record.
+ *
+ *    update pool=<pool-name>
+ *        updates pool from Pool resource
+ *    update media pool=<pool-name> volume=<volume-name>
+ *        changes pool info for volume
+ *    update slots [scan=...]
+ *        updates autochanger slots
+ */
+int update_cmd(UAContext *ua, const char *cmd)
+{
+   static const char *kw[] = {
+      N_("media"),  /* 0 */
+      N_("volume"), /* 1 */
+      N_("pool"),   /* 2 */
+      N_("slots"),  /* 3 */
+      NULL};
+
+   if (!open_db(ua)) {
+      return 1;
+   }
+
+   switch (find_arg_keyword(ua, kw)) {
+   case 0:
+   case 1:
+      update_volume(ua);
+      return 1;
+   case 2:
+      update_pool(ua);
+      return 1;
+   case 3:
+      update_slots(ua);
+      return 1;
+   default:
+      break;
+   }
+
+   start_prompt(ua, _("Update choice:\n"));
+   add_prompt(ua, _("Volume parameters"));
+   add_prompt(ua, _("Pool from resource"));
+   add_prompt(ua, _("Slots from autochanger"));
+   switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
+   case 0:
+      update_volume(ua);
+      break;
+   case 1:
+      update_pool(ua);
+      break;
+   case 2:
+      update_slots(ua);
+      break;
+   default:
+      break;
+   }
+   return 1;
+}
+
+static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
+{
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   const char *kw[] = {
+      "Append",
+      "Archive",
+      "Disabled",
+      "Full",
+      "Used",
+      "Cleaning",
+      "Recycle",
+      "Read-Only",
+      NULL};
+   bool found = false;
+   int i;
+
+   for (i=0; kw[i]; i++) {
+      if (strcasecmp(val, kw[i]) == 0) {
+        found = true;
+        break;
+      }
+   }
+   if (!found) {
+      bsendmsg(ua, _("Invalid VolStatus specified: %s\n"), val);
+   } else {
+      char ed1[50];
+      bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
+      Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
+        mr->VolStatus, edit_int64(mr->MediaId,ed1));
+      if (!db_sql_query(ua->db, query, NULL, NULL)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+      } else {
+         bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
+      }
+   }
+   free_pool_memory(query);
+}
+
+static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   char ed1[150], ed2[50];
+   POOLMEM *query;
+   if (!duration_to_utime(val, &mr->VolRetention)) {
+      bsendmsg(ua, _("Invalid retention period specified: %s\n"), val);
+      return;
+   }
+   query = get_pool_memory(PM_MESSAGE);
+   Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
+      edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New retention period is: %s\n"),
+        edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
+   }
+   free_pool_memory(query);
+}
+
+static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   char ed1[150], ed2[50];
+   POOLMEM *query;
+
+   if (!duration_to_utime(val, &mr->VolUseDuration)) {
+      bsendmsg(ua, _("Invalid use duration specified: %s\n"), val);
+      return;
+   }
+   query = get_pool_memory(PM_MESSAGE);
+   Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
+      edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New use duration is: %s\n"),
+        edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
+   }
+   free_pool_memory(query);
+}
+
+static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   char ed1[50];
+   Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
+      val, edit_int64(mr->MediaId,ed1));
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New max jobs is: %s\n"), val);
+   }
+   free_pool_memory(query);
+}
+
+static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   char ed1[50];
+   Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
+      val, edit_int64(mr->MediaId, ed1));
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New max files is: %s\n"), val);
+   }
+   free_pool_memory(query);
+}
+
+static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   uint64_t maxbytes;
+   char ed1[50], ed2[50];
+   POOLMEM *query;
+
+   if (!size_to_uint64(val, strlen(val), &maxbytes)) {
+      bsendmsg(ua, _("Invalid max. bytes specification: %s\n"), val);
+      return;
+   }
+   query = get_pool_memory(PM_MESSAGE);
+   Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
+      edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
+   }
+   free_pool_memory(query);
+}
+
+static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   int recycle;
+   char ed1[50];
+   POOLMEM *query;
+   if (strcasecmp(val, _("yes")) == 0) {
+      recycle = 1;
+   } else if (strcasecmp(val, _("no")) == 0) {
+      recycle = 0;
+   } else {
+      bsendmsg(ua, _("Invalid value. It must by yes or no.\n"));
+      return;
+   }
+   query = get_pool_memory(PM_MESSAGE);
+   Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
+      recycle, edit_int64(mr->MediaId, ed1));
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New Recycle flag is: %s\n"),
+         mr->Recycle==1?_("yes"):_("no"));
+   }
+   free_pool_memory(query);
+}
+
+/* Modify the Pool in which this Volume is located */
+static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
+{
+   POOL_DBR pr;
+   POOLMEM *query;
+   char ed1[50];
+
+   memset(&pr, 0, sizeof(pr));
+   bstrncpy(pr.Name, val, sizeof(pr.Name));
+   if (!get_pool_dbr(ua, &pr)) {
+      return;
+   }
+   mr->PoolId = pr.PoolId;           /* set new PoolId */
+   /*
+    */
+   query = get_pool_memory(PM_MESSAGE);
+   db_lock(ua->db);
+   Mmsg(query, "UPDATE Media SET PoolId=%d WHERE MediaId=%s",
+      mr->PoolId, edit_int64(mr->MediaId, ed1));
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
+      opr->NumVols--;
+      if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+      }
+      pr.NumVols++;
+      if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+      }
+   }
+   db_unlock(ua->db);
+   free_pool_memory(query);
+}
+
+/*
+ * Refresh the Volume information from the Pool record
+ */
+static void update_volfrompool(UAContext *ua, MEDIA_DBR *mr)
+{
+   POOL_DBR pr;
+
+   memset(&pr, 0, sizeof(pr));
+   pr.PoolId = mr->PoolId;
+   if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
+       !acl_access_ok(ua, Pool_ACL, pr.Name)) {
+      return;
+   }
+   set_pool_dbr_defaults_in_media_dbr(mr, &pr);
+   if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
+      bsendmsg(ua, _("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("Volume defaults updated from \"%s\" Pool record.\n"),
+        pr.Name);
+   }
+}
+
+/*
+ * Refresh the Volume information from the Pool record
+ *   for all Volumes
+ */
+static void update_all_vols_from_pool(UAContext *ua)
+{
+   POOL_DBR pr;
+   MEDIA_DBR mr;
+
+   memset(&pr, 0, sizeof(pr));
+   memset(&mr, 0, sizeof(mr));
+   if (!get_pool_dbr(ua, &pr)) {
+      return;
+   }
+   set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
+   mr.PoolId = pr.PoolId;
+   if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
+      bsendmsg(ua, _("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("All Volume defaults updated from Pool record.\n"));
+   }
+}
+
+
+/*
+ * Update a media record -- allows you to change the
+ *  Volume status. E.g. if you want Bacula to stop
+ *  writing on the volume, set it to anything other
+ *  than Append.
+ */
+static int update_volume(UAContext *ua)
+{
+   MEDIA_DBR mr;
+   POOL_DBR pr;
+   POOLMEM *query;
+   char ed1[130];
+   bool done = false;
+   const char *kw[] = {
+      N_("VolStatus"),                /* 0 */
+      N_("VolRetention"),             /* 1 */
+      N_("VolUse"),                   /* 2 */
+      N_("MaxVolJobs"),               /* 3 */
+      N_("MaxVolFiles"),              /* 4 */
+      N_("MaxVolBytes"),              /* 5 */
+      N_("Recycle"),                  /* 6 */
+      N_("Pool"),                     /* 7 */
+      N_("FromPool"),                 /* 8 */
+      N_("AllFromPool"),              /* 9 */
+      NULL };
+
+   for (int i=0; kw[i]; i++) {
+      int j;
+      POOL_DBR pr;
+      if ((j=find_arg_with_value(ua, kw[i])) > 0) {
+        if (i != 9 && !select_media_dbr(ua, &mr)) {
+           return 0;
+        }
+        switch (i) {
+        case 0:
+           update_volstatus(ua, ua->argv[j], &mr);
+           break;
+        case 1:
+           update_volretention(ua, ua->argv[j], &mr);
+           break;
+        case 2:
+           update_voluseduration(ua, ua->argv[j], &mr);
+           break;
+        case 3:
+           update_volmaxjobs(ua, ua->argv[j], &mr);
+           break;
+        case 4:
+           update_volmaxfiles(ua, ua->argv[j], &mr);
+           break;
+        case 5:
+           update_volmaxbytes(ua, ua->argv[j], &mr);
+           break;
+        case 6:
+           update_volrecycle(ua, ua->argv[j], &mr);
+           break;
+        case 7:
+           memset(&pr, 0, sizeof(POOL_DBR));
+           pr.PoolId = mr.PoolId;
+           if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
+               bsendmsg(ua, "%s", db_strerror(ua->db));
+              break;
+           }
+           update_vol_pool(ua, ua->argv[j], &mr, &pr);
+           break;
+        case 8:
+           update_volfrompool(ua, &mr);
+           return 1;
+        case 9:
+           update_all_vols_from_pool(ua);
+           return 1;
+        }
+        done = true;
+      }
+   }
+
+   for ( ; !done; ) {
+      if (!select_media_dbr(ua, &mr)) {
+        return 0;
+      }
+      bsendmsg(ua, _("Updating Volume \"%s\"\n"), mr.VolumeName);
+      start_prompt(ua, _("Parameters to modify:\n"));
+      add_prompt(ua, _("Volume Status"));
+      add_prompt(ua, _("Volume Retention Period"));
+      add_prompt(ua, _("Volume Use Duration"));
+      add_prompt(ua, _("Maximum Volume Jobs"));
+      add_prompt(ua, _("Maximum Volume Files"));
+      add_prompt(ua, _("Maximum Volume Bytes"));
+      add_prompt(ua, _("Recycle Flag"));
+      add_prompt(ua, _("Slot"));
+      add_prompt(ua, _("InChanger Flag"));
+      add_prompt(ua, _("Volume Files"));
+      add_prompt(ua, _("Pool"));
+      add_prompt(ua, _("Volume from Pool"));
+      add_prompt(ua, _("All Volumes from Pool"));
+      add_prompt(ua, _("Done"));
+      switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
+      case 0:                        /* Volume Status */
+        /* Modify Volume Status */
+         bsendmsg(ua, _("Current Volume status is: %s\n"), mr.VolStatus);
+         start_prompt(ua, _("Possible Values are:\n"));
+         add_prompt(ua, "Append");      /* Better not translate these as */
+         add_prompt(ua, "Archive");     /* They are known in the database code */
+         add_prompt(ua, "Disabled");
+         add_prompt(ua, "Full");
+         add_prompt(ua, "Used");
+         add_prompt(ua, "Cleaning");
+         if (strcmp(mr.VolStatus, "Purged") == 0) {
+            add_prompt(ua, "Recycle");
+        }
+         add_prompt(ua, "Read-Only");
+         if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
+           return 1;
+        }
+        update_volstatus(ua, ua->cmd, &mr);
+        break;
+      case 1:                        /* Retention */
+         bsendmsg(ua, _("Current retention period is: %s\n"),
+           edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
+         if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
+           return 0;
+        }
+        update_volretention(ua, ua->cmd, &mr);
+        break;
+
+      case 2:                        /* Use Duration */
+         bsendmsg(ua, _("Current use duration is: %s\n"),
+           edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
+         if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
+           return 0;
+        }
+        update_voluseduration(ua, ua->cmd, &mr);
+        break;
+
+      case 3:                        /* Max Jobs */
+         bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
+         if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
+           return 0;
+        }
+        update_volmaxjobs(ua, ua->cmd, &mr);
+        break;
+
+      case 4:                        /* Max Files */
+         bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
+         if (!get_pint(ua, _("Enter new Maximum Files: "))) {
+           return 0;
+        }
+        update_volmaxfiles(ua, ua->cmd, &mr);
+        break;
+
+      case 5:                        /* Max Bytes */
+         bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
+         if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
+           return 0;
+        }
+        update_volmaxbytes(ua, ua->cmd, &mr);
+        break;
+
+
+      case 6:                        /* Recycle */
+         bsendmsg(ua, _("Current recycle flag is: %s\n"),
+            mr.Recycle==1?_("yes"):_("no"));
+         if (!get_yesno(ua, _("Enter new Recycle status: "))) {
+           return 0;
+        }
+        update_volrecycle(ua, ua->cmd, &mr);
+        break;
+
+      case 7:                        /* Slot */
+        int Slot;
+
+        memset(&pr, 0, sizeof(POOL_DBR));
+        pr.PoolId = mr.PoolId;
+        if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
+            bsendmsg(ua, "%s", db_strerror(ua->db));
+           return 0;
+        }
+         bsendmsg(ua, _("Current Slot is: %d\n"), mr.Slot);
+         if (!get_pint(ua, _("Enter new Slot: "))) {
+           return 0;
+        }
+        Slot = ua->pint32_val;
+        if (pr.MaxVols > 0 && Slot > (int)pr.MaxVols) {
+            bsendmsg(ua, _("Invalid slot, it must be between 0 and %d\n"),
+              pr.MaxVols);
+           break;
+        }
+        mr.Slot = Slot;
+        /*
+         * Make sure to use db_update... rather than doing this directly,
+         *   so that any Slot is handled correctly.
+         */
+        if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
+            bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
+        } else {
+            bsendmsg(ua, _("New Slot is: %d\n"), mr.Slot);
+        }
+        break;
+
+      case 8:                        /* InChanger */
+         bsendmsg(ua, _("Current InChanger flag is: %d\n"), mr.InChanger);
+         if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
+           return 0;
+        }
+        mr.InChanger = ua->pint32_val;
+        /*
+         * Make sure to use db_update... rather than doing this directly,
+         *   so that any Slot is handled correctly.
+         */
+        if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
+            bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
+        } else {
+            bsendmsg(ua, _("New InChanger flag is: %d\n"), mr.InChanger);
+        }
+        break;
+
+
+      case 9:                        /* Volume Files */
+        int32_t VolFiles;
+         bsendmsg(ua, _("Warning changing Volume Files can result\n"
+                        "in loss of data on your Volume\n\n"));
+         bsendmsg(ua, _("Current Volume Files is: %u\n"), mr.VolFiles);
+         if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
+           return 0;
+        }
+        VolFiles = ua->pint32_val;
+        if (VolFiles != (int)(mr.VolFiles + 1)) {
+            bsendmsg(ua, _("Normally, you should only increase Volume Files by one!\n"));
+            if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
+              break;
+           }
+        }
+        query = get_pool_memory(PM_MESSAGE);
+         Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
+           VolFiles, edit_int64(mr.MediaId, ed1));
+        if (!db_sql_query(ua->db, query, NULL, NULL)) {
+            bsendmsg(ua, "%s", db_strerror(ua->db));
+        } else {
+            bsendmsg(ua, _("New Volume Files is: %u\n"), VolFiles);
+        }
+        free_pool_memory(query);
+        break;
+
+      case 10:                        /* Volume's Pool */
+        memset(&pr, 0, sizeof(POOL_DBR));
+        pr.PoolId = mr.PoolId;
+        if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
+            bsendmsg(ua, "%s", db_strerror(ua->db));
+           return 0;
+        }
+         bsendmsg(ua, _("Current Pool is: %s\n"), pr.Name);
+         if (!get_cmd(ua, _("Enter new Pool name: "))) {
+           return 0;
+        }
+        update_vol_pool(ua, ua->cmd, &mr, &pr);
+        return 1;
+
+      case 11:
+        update_volfrompool(ua, &mr);
+        return 1;
+      case 12:
+        update_all_vols_from_pool(ua);
+        return 1;
+      default:                       /* Done or error */
+         bsendmsg(ua, "Selection done.\n");
+        return 1;
+      }
+   }
+   return 1;
+}
+
+/*
+ * Update pool record -- pull info from current POOL resource
+ */
+static int update_pool(UAContext *ua)
+{
+   POOL_DBR  pr;
+   int id;
+   POOL *pool;
+   POOLMEM *query;
+
+   pool = get_pool_resource(ua);
+   if (!pool) {
+      return 0;
+   }
+
+   memset(&pr, 0, sizeof(pr));
+   bstrncpy(pr.Name, pool->hdr.name, sizeof(pr.Name));
+   if (!get_pool_dbr(ua, &pr)) {
+      return 0;
+   }
+
+   set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
+
+   id = db_update_pool_record(ua->jcr, ua->db, &pr);
+   if (id <= 0) {
+      bsendmsg(ua, _("db_update_pool_record returned %d. ERR=%s\n"),
+        id, db_strerror(ua->db));
+   }
+   query = get_pool_memory(PM_MESSAGE);
+   Mmsg(query, list_pool, pr.PoolId);
+   db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
+   free_pool_memory(query);
+   bsendmsg(ua, _("Pool DB record updated from resource.\n"));
+   return 1;
+}
index a62b6c50c6481f0d1ebe4fd3754fccd0a9656b9b..2cef7c32e9ad374406947ebc16ed2f4c2c9d0c86 100644 (file)
@@ -108,7 +108,7 @@ POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool)
         pool_ctl[pool].max_used = pool_ctl[pool].in_use;
       }
       V(mutex);
-      Dmsg3(800, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
+      Dmsg3(1800, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
       sm_new_owner(fname, lineno, (char *)buf);
       return (POOLMEM *)((char *)buf+HEAD_SIZE);
    }
@@ -124,7 +124,7 @@ POOLMEM *sm_get_pool_memory(const char *fname, int lineno, int pool)
       pool_ctl[pool].max_used = pool_ctl[pool].in_use;
    }
    V(mutex);
-   Dmsg3(800, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
+   Dmsg3(1800, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
    return (POOLMEM *)((char *)buf+HEAD_SIZE);
 }
 
@@ -209,7 +209,7 @@ void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
       /* Don't let him free the same buffer twice */
       for (next=pool_ctl[pool].free_buf; next; next=next->next) {
         if (next == buf) {
-            Dmsg4(800, "bad free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
+            Dmsg4(1800, "bad free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
            V(mutex);                 /* unblock the pool */
            ASSERT(next != buf);      /* attempt to free twice */
         }
@@ -218,7 +218,7 @@ void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
       buf->next = pool_ctl[pool].free_buf;
       pool_ctl[pool].free_buf = buf;
    }
-   Dmsg4(800, "free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
+   Dmsg4(1800, "free_pool_memory %x pool=%d from %s:%d\n", buf, pool, fname, lineno);
    V(mutex);
 }
 
@@ -347,7 +347,7 @@ void free_pool_memory(POOLMEM *obuf)
       buf->next = pool_ctl[pool].free_buf;
       pool_ctl[pool].free_buf = buf;
    }
-   Dmsg2(800, "free_pool_memory %x pool=%d\n", buf, pool);
+   Dmsg2(1800, "free_pool_memory %x pool=%d\n", buf, pool);
    V(mutex);
 }
 
index a08e51ed55244f2854d3a52541b0610c11a3377c..68da73265d94e42f33dc3f200924acf5b2beccdd 100755 (executable)
@@ -283,7 +283,7 @@ walk_list:
         timeout.tv_sec++;
       }
 
-      Dmsg1(900, "pthread_cond_timedwait %d\n", timeout.tv_sec - tv.tv_sec);
+      Dmsg1(1900, "pthread_cond_timedwait %d\n", timeout.tv_sec - tv.tv_sec);
       /* Note, this unlocks mutex during the sleep */
       P(timer_mutex);
       pthread_cond_timedwait(&timer, &timer_mutex, &timeout);
index 71db9dc80a0f0b2e0813fb13935825146d48726b..f127e96fe20bbafb14c3b1d6d308e2b2641c992c 100644 (file)
@@ -159,7 +159,7 @@ static int get_autochanger_loaded_slot(DCR *dcr)
        drive);
    changer = edit_device_codes(dcr, changer, "loaded");
    status = run_program(changer, timeout, results);
-   Dmsg3(50, "run_prog: %s stat=%d result=%s\n", changer, status, results);
+   Dmsg3(50, "run_prog: %s stat=%d result=%s", changer, status, results);
    if (status == 0) {
       loaded = atoi(results);
       if (loaded > 0) {
@@ -223,7 +223,7 @@ void mark_volume_not_inchanger(DCR *dcr)
  *   with their barcodes.
  *   We assume that it is always the Console that is calling us.
  */
-bool autochanger_list(DCR *dcr, BSOCK *dir)
+bool autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd)  
 {
    DEVICE *dev = dcr->dev;
    JCR *jcr = dcr->jcr;
@@ -232,6 +232,8 @@ bool autochanger_list(DCR *dcr, BSOCK *dir)
    BPIPE *bpipe;
    int slot, loaded;
    int len = sizeof_pool_memory(dir->msg) - 1;
+   bool ok = false;
+   int stat;
 
    if (!dev_cap(dev, CAP_AUTOCHANGER) || !dcr->device->changer_name ||
        !dcr->device->changer_command) {
@@ -240,49 +242,73 @@ bool autochanger_list(DCR *dcr, BSOCK *dir)
    }
 
    changer = get_pool_memory(PM_FNAME);
-   offline_or_rewind_dev(dev);
-   /* We are going to load a new tape, so close the device */
-   force_close_dev(dev);
+   /* List command? */
+   if (strcmp(cmd, "list") == 0) {
+      int drive = dev->device->drive_index;
+      /* Yes, to get a good listing, we unload any volumes */
+      offline_or_rewind_dev(dev);
+      /* We are going to load a new tape, so close the device */
+      force_close_dev(dev);
 
-   /* First unload any tape */
-   loaded = get_autochanger_loaded_slot(dcr);
-   if (loaded > 0) {
-      bnet_fsend(dir, _("3305 Issuing autochanger \"unload slot %d\" command.\n"), loaded);
-      slot = dcr->VolCatInfo.Slot;
-      dcr->VolCatInfo.Slot = loaded;
-      changer = edit_device_codes(dcr, changer, "unload");
-      int stat = run_program(changer, timeout, NULL);
-      if (stat != 0) {
-        berrno be;
-        be.set_errno(stat);
-         Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d\" command: ERR=%s.\n"),
-             loaded, be.strerror());
+      /* First unload any tape */
+      loaded = get_autochanger_loaded_slot(dcr);
+      if (loaded > 0) {
+        bnet_fsend(dir,
+            _("3305 Issuing autochanger \"unload slot %d, drive %d\" command.\n"),
+           loaded, drive);
+        slot = dcr->VolCatInfo.Slot;
+        dcr->VolCatInfo.Slot = loaded;
+         changer = edit_device_codes(dcr, changer, "unload");
+        lock_changer(dcr);
+        int stat = run_program(changer, timeout, NULL);
+        unlock_changer(dcr);
+        if (stat != 0) {
+           berrno be;
+           be.set_errno(stat);
+            Jmsg(jcr, M_INFO, 0, _("3995 Bad autochanger \"unload slot %d, drive %d\": ERR=%s.\n"),
+                   slot, drive, be.strerror());
+        }
+        dcr->VolCatInfo.Slot = slot;
       }
-      dcr->VolCatInfo.Slot = slot;
    }
 
-   /* Now list slots occupied */
-   changer = edit_device_codes(dcr, changer, "list");
-   bnet_fsend(dir, _("3306 Issuing autochanger \"list\" command.\n"));
+   /* Now issue the command */
+   changer = edit_device_codes(dcr, changer, cmd);
+   bnet_fsend(dir, _("3306 Issuing autochanger \"%s\" command.\n"), cmd);
+   lock_changer(dcr);
    bpipe = open_bpipe(changer, timeout, "r");
    if (!bpipe) {
+      unlock_changer(dcr);
       bnet_fsend(dir, _("3993 Open bpipe failed.\n"));
-      free_pool_memory(changer);
-      return false;
+      goto bail_out;
    }
-   /* Get output from changer */
-   while (fgets(dir->msg, len, bpipe->rfd)) {
+   if (strcmp(cmd, "list") == 0) {
+      /* Get output from changer */
+      while (fgets(dir->msg, len, bpipe->rfd)) {
+        dir->msglen = strlen(dir->msg);
+         Dmsg1(100, "<stored: %s\n", dir->msg);
+        bnet_send(dir);
+      }
+   } else {
+      /* For slots command, read a single line */
+      bstrncpy(dir->msg, "slots=", len);
+      fgets(dir->msg+6, len-6, bpipe->rfd);
       dir->msglen = strlen(dir->msg);
+      Dmsg1(100, "<stored: %s", dir->msg);
       bnet_send(dir);
    }
-   int stat = close_bpipe(bpipe);
+                
+   stat = close_bpipe(bpipe);
+   unlock_changer(dcr);
    if (stat != 0) {
       berrno be;
       be.set_errno(stat);
       bnet_fsend(dir, "Autochanger error: ERR=%s\n", be.strerror());
    }
    bnet_sig(dir, BNET_EOD);
+   ok = true;
 
+bail_out:
    free_pool_memory(changer);
    return true;
 }
@@ -315,7 +341,7 @@ char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd)
    const char *imsg = dcr->device->changer_command;
 
    *omsg = 0;
-   Dmsg1(800, "edit_device_codes: %s\n", imsg);
+   Dmsg1(1800, "edit_device_codes: %s\n", imsg);
    for (p=imsg; *p; p++) {
       if (*p == '%') {
         switch (*++p) {
@@ -365,9 +391,10 @@ char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd)
         add[1] = 0;
         str = add;
       }
-      Dmsg1(900, "add_str %s\n", str);
+      Dmsg1(1900, "add_str %s\n", str);
       pm_strcat(&omsg, (char *)str);
-      Dmsg1(800, "omsg=%s\n", omsg);
+      Dmsg1(1800, "omsg=%s\n", omsg);
    }
+   Dmsg1(800, "omsg=%s\n", omsg);
    return omsg;
 }
index f4ac283fcf84a75e37546fd2354be85f2705051e..201d301fb630325b4c331faf26279db630b33917 100644 (file)
@@ -782,8 +782,17 @@ static bool autochanger_cmd(JCR *jcr)
    BSOCK *dir = jcr->dir_bsock;
    DEVICE *dev;
    DCR *dcr;
+   const char *cmd;
+   bool ok = false;
 
    if (sscanf(dir->msg, "autochanger list %127s ", devname.c_str()) == 1) {
+      cmd = "list";
+      ok = true;
+   } else if (sscanf(dir->msg, "autochanger slots %127s ", devname.c_str()) == 1) {
+      cmd = "slots";
+      ok = true;
+   }
+   if (ok) {
       dev = find_device(jcr, devname);
       dcr = jcr->dcr;
       if (dev) {
@@ -792,17 +801,17 @@ static bool autochanger_cmd(JCR *jcr)
             bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), 
               dev->print_name());
         } else if (!dev->is_open()) {
-           autochanger_list(dcr, dir);
+           autochanger_cmd(dcr, dir, cmd);
          /* Under certain "safe" conditions, we can steal the lock */
         } else if (dev->dev_blocked &&
                    (dev->dev_blocked == BST_UNMOUNTED ||
                     dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
                     dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP)) {
-           autochanger_list(dcr, dir);
+           autochanger_cmd(dcr, dir, cmd);
         } else if (dev->is_busy()) {
            send_dir_busy_message(dir, dev);
         } else {                     /* device not being used */
-           autochanger_list(dcr, dir);
+           autochanger_cmd(dcr, dir, cmd);
         }
         V(dev->mutex);
       } else {
@@ -810,8 +819,8 @@ static bool autochanger_cmd(JCR *jcr)
       }
    } else {  /* error on scanf */
       pm_strcpy(jcr->errmsg, dir->msg);
-      bnet_fsend(dir, _("3908 Error scanning autocharger list command: %s\n"),
-        jcr->errmsg);
+      bnet_fsend(dir, _("3908 Error scanning autocharger %s command: %s\n"),
+        cmd, jcr->errmsg);
    }
    bnet_sig(dir, BNET_EOD);
    return true;
index 7730845939977a6172cca6a008204cd3d2ad9a28..6ec0b722ea789ab047538ed141a2d506e9635503 100644 (file)
@@ -58,7 +58,7 @@ int     authenticate_filed(JCR *jcr);
 
 /* From autochanger.c */
 int      autoload_device(DCR *dcr, int writing, BSOCK *dir);
-bool     autochanger_list(DCR *dcr, BSOCK *dir);
+bool     autochanger_cmd(DCR *dcr, BSOCK *dir, const char *cmd);
 void     mark_volume_not_inchanger(DCR *dcr);
 char    *edit_device_codes(DCR *dcr, char *omsg, const char *cmd);
 
index 8d7a7f6be60c94139f7ec0d3d6e3dfb063337401..780da7da6322975be5afcdbd2c02e4d2d86e945f 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #undef  VERSION
 #define VERSION "1.37.6"
-#define BDATE   "09 March 2005"
-#define LSMDATE "09Mar05"
+#define BDATE   "10 March 2005"
+#define LSMDATE "10Mar05"
 
 /* Debug flags */
 #undef  DEBUG