2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
30 * Bacula Director -- Update command processing
31 * Split from ua_cmds.c March 2005
33 * Kern Sibbald, September MM
41 /* Forward referenced functions */
42 static int update_volume(UAContext *ua);
43 static bool update_pool(UAContext *ua);
44 static bool update_job(UAContext *ua);
45 static bool update_stats(UAContext *ua);
48 * Update a Pool Record in the database.
49 * It is always updated from the Resource record.
51 * update pool=<pool-name>
52 * updates pool from Pool resource
53 * update media pool=<pool-name> volume=<volume-name>
54 * changes pool info for volume
55 * update slots [scan=...]
56 * updates autochanger slots
57 * update stats [days=...]
58 * updates long term statistics
60 int update_cmd(UAContext *ua, const char *cmd)
62 static const char *kw[] = {
64 NT_("volume"), /* 1 */
71 if (!open_client_db(ua)) {
75 switch (find_arg_keyword(ua, kw)) {
96 start_prompt(ua, _("Update choice:\n"));
97 add_prompt(ua, _("Volume parameters"));
98 add_prompt(ua, _("Pool from resource"));
99 add_prompt(ua, _("Slots from autochanger"));
100 add_prompt(ua, _("Long term statistics"));
101 switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
120 static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr)
122 POOL_MEM query(PM_MESSAGE);
137 for (i=0; kw[i]; i++) {
138 if (strcasecmp(val, kw[i]) == 0) {
144 ua->error_msg(_("Invalid VolStatus specified: %s\n"), val);
147 bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus));
148 Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s",
149 mr->VolStatus, edit_int64(mr->MediaId,ed1));
150 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
151 ua->error_msg("%s", db_strerror(ua->db));
153 ua->info_msg(_("New Volume status is: %s\n"), mr->VolStatus);
158 static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
160 char ed1[150], ed2[50];
161 POOL_MEM query(PM_MESSAGE);
162 if (!duration_to_utime(val, &mr->VolRetention)) {
163 ua->error_msg(_("Invalid retention period specified: %s\n"), val);
166 Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s",
167 edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2));
168 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
169 ua->error_msg("%s", db_strerror(ua->db));
171 ua->info_msg(_("New retention period is: %s\n"),
172 edit_utime(mr->VolRetention, ed1, sizeof(ed1)));
176 static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
178 char ed1[150], ed2[50];
179 POOL_MEM query(PM_MESSAGE);
181 if (!duration_to_utime(val, &mr->VolUseDuration)) {
182 ua->error_msg(_("Invalid use duration specified: %s\n"), val);
185 Mmsg(query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%s",
186 edit_uint64(mr->VolUseDuration, ed1), edit_int64(mr->MediaId,ed2));
187 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
188 ua->error_msg("%s", db_strerror(ua->db));
190 ua->info_msg(_("New use duration is: %s\n"),
191 edit_utime(mr->VolUseDuration, ed1, sizeof(ed1)));
195 static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
197 POOL_MEM query(PM_MESSAGE);
199 Mmsg(query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%s",
200 val, edit_int64(mr->MediaId,ed1));
201 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
202 ua->error_msg("%s", db_strerror(ua->db));
204 ua->info_msg(_("New max jobs is: %s\n"), val);
208 static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
210 POOL_MEM query(PM_MESSAGE);
212 Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s",
213 val, edit_int64(mr->MediaId, ed1));
214 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
215 ua->error_msg("%s", db_strerror(ua->db));
217 ua->info_msg(_("New max files is: %s\n"), val);
221 static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
224 char ed1[50], ed2[50];
225 POOL_MEM query(PM_MESSAGE);
227 if (!size_to_uint64(val, strlen(val), &maxbytes)) {
228 ua->error_msg(_("Invalid max. bytes specification: %s\n"), val);
231 Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s",
232 edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2));
233 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
234 ua->error_msg("%s", db_strerror(ua->db));
236 ua->info_msg(_("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
240 static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
245 POOL_MEM query(PM_MESSAGE);
246 if (!is_yesno(val, &recycle)) {
247 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
250 Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s",
251 recycle, edit_int64(mr->MediaId, ed1));
252 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
253 ua->error_msg("%s", db_strerror(ua->db));
255 ua->info_msg(_("New Recycle flag is: %s\n"),
256 recycle==1?_("yes"):_("no"));
260 static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr)
265 POOL_MEM query(PM_MESSAGE);
266 if (!is_yesno(val, &InChanger)) {
267 ua->error_msg(_("Invalid value. It must be yes or no.\n"));
270 Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s",
271 InChanger, edit_int64(mr->MediaId, ed1));
272 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
273 ua->error_msg("%s", db_strerror(ua->db));
275 ua->info_msg(_("New InChanger flag is: %s\n"),
276 InChanger==1?_("yes"):_("no"));
281 static void update_volslot(UAContext *ua, char *val, MEDIA_DBR *mr)
285 memset(&pr, 0, sizeof(POOL_DBR));
286 pr.PoolId = mr->PoolId;
287 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
288 ua->error_msg("%s", db_strerror(ua->db));
291 mr->Slot = atoi(val);
292 if (pr.MaxVols > 0 && mr->Slot > (int)pr.MaxVols) {
293 ua->error_msg(_("Invalid slot, it must be between 0 and MaxVols=%d\n"),
298 * Make sure to use db_update... rather than doing this directly,
299 * so that any Slot is handled correctly.
301 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
302 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
304 ua->info_msg(_("New Slot is: %d\n"), mr->Slot);
308 /* Modify the Pool in which this Volume is located */
309 void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
312 POOL_MEM query(PM_MESSAGE);
313 char ed1[50], ed2[50];
315 memset(&pr, 0, sizeof(pr));
316 bstrncpy(pr.Name, val, sizeof(pr.Name));
317 if (!get_pool_dbr(ua, &pr)) {
320 mr->PoolId = pr.PoolId; /* set new PoolId */
324 Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s",
325 edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2));
326 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
327 ua->error_msg("%s", db_strerror(ua->db));
329 ua->info_msg(_("New Pool is: %s\n"), pr.Name);
331 if (!db_update_pool_record(ua->jcr, ua->db, opr)) {
332 ua->error_msg("%s", db_strerror(ua->db));
335 if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
336 ua->error_msg("%s", db_strerror(ua->db));
342 /* Modify the RecyclePool of a Volume */
343 void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr)
346 POOL_MEM query(PM_MESSAGE);
347 char ed1[50], ed2[50], *poolname;
349 if(val && *val) { /* update volume recyclepool="Scratch" */
350 /* If a pool name is given, look up the PoolId */
351 memset(&pr, 0, sizeof(pr));
352 bstrncpy(pr.Name, val, sizeof(pr.Name));
353 if (!get_pool_dbr(ua, &pr, NT_("recyclepool"))) {
356 /* pool = select_pool_resource(ua); */
357 mr->RecyclePoolId = pr.PoolId; /* get the PoolId */
360 } else { /* update volume recyclepool="" */
361 /* If no pool name is given, set the PoolId to 0 (the default) */
362 mr->RecyclePoolId = 0;
363 poolname = _("*None*");
367 Mmsg(query, "UPDATE Media SET RecyclePoolId=%s WHERE MediaId=%s",
368 edit_int64(mr->RecyclePoolId, ed1), edit_int64(mr->MediaId, ed2));
369 if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) {
370 ua->error_msg("%s", db_strerror(ua->db));
372 ua->info_msg(_("New RecyclePool is: %s\n"), poolname);
378 * Refresh the Volume information from the Pool record
380 static void update_vol_from_pool(UAContext *ua, MEDIA_DBR *mr)
384 memset(&pr, 0, sizeof(pr));
385 pr.PoolId = mr->PoolId;
386 if (!db_get_pool_record(ua->jcr, ua->db, &pr) ||
387 !acl_access_ok(ua, Pool_ACL, pr.Name)) {
390 set_pool_dbr_defaults_in_media_dbr(mr, &pr);
391 if (!db_update_media_defaults(ua->jcr, ua->db, mr)) {
392 ua->error_msg(_("Error updating Volume record: ERR=%s"), db_strerror(ua->db));
394 ua->info_msg(_("Volume defaults updated from \"%s\" Pool record.\n"),
400 * Refresh the Volume information from the Pool record
403 static void update_all_vols_from_pool(UAContext *ua, const char *pool_name)
408 memset(&pr, 0, sizeof(pr));
409 memset(&mr, 0, sizeof(mr));
411 bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
412 if (!get_pool_dbr(ua, &pr)) {
415 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
416 mr.PoolId = pr.PoolId;
417 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
418 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
420 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
425 static void update_all_vols(UAContext *ua)
432 memset(&pr, 0, sizeof(pr));
433 memset(&mr, 0, sizeof(mr));
435 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
436 ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
440 for (i=0; i<num_pools; i++) {
442 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { /* ***FIXME*** use acl? */
443 ua->warning_msg(_("Updating all pools, but skipped PoolId=%d. ERR=%s\n"), db_strerror(ua->db));
447 set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
448 mr.PoolId = pr.PoolId;
450 if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
451 ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
453 ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
461 static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
463 mr->Enabled = get_enabled(ua, val);
464 if (mr->Enabled < 0) {
467 if (!db_update_media_record(ua->jcr, ua->db, mr)) {
468 ua->error_msg(_("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
470 ua->info_msg(_("New Enabled is: %d\n"), mr->Enabled);
477 * Update a media record -- allows you to change the
478 * Volume status. E.g. if you want Bacula to stop
479 * writing on the volume, set it to anything other
482 static int update_volume(UAContext *ua)
493 NT_("VolStatus"), /* 0 */
494 NT_("VolRetention"), /* 1 */
495 NT_("VolUse"), /* 2 */
496 NT_("MaxVolJobs"), /* 3 */
497 NT_("MaxVolFiles"), /* 4 */
498 NT_("MaxVolBytes"), /* 5 */
499 NT_("Recycle"), /* 6 */
500 NT_("InChanger"), /* 7 */
503 NT_("FromPool"), /* 10 */
504 NT_("AllFromPool"), /* 11 !!! see below !!! */
505 NT_("Enabled"), /* 12 */
506 NT_("RecyclePool"), /* 13 */
509 #define AllFromPool 11 /* keep this updated with above */
511 for (i=0; kw[i]; i++) {
515 if ((j=find_arg_with_value(ua, kw[i])) > 0) {
516 /* If all from pool don't select a media record */
517 if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
522 update_volstatus(ua, ua->argv[j], &mr);
525 update_volretention(ua, ua->argv[j], &mr);
528 update_voluseduration(ua, ua->argv[j], &mr);
531 update_volmaxjobs(ua, ua->argv[j], &mr);
534 update_volmaxfiles(ua, ua->argv[j], &mr);
537 update_volmaxbytes(ua, ua->argv[j], &mr);
540 update_volrecycle(ua, ua->argv[j], &mr);
543 update_volinchanger(ua, ua->argv[j], &mr);
546 update_volslot(ua, ua->argv[j], &mr);
549 memset(&pr, 0, sizeof(POOL_DBR));
550 pr.PoolId = mr.PoolId;
551 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
552 ua->error_msg("%s", db_strerror(ua->db));
555 update_vol_pool(ua, ua->argv[j], &mr, &pr);
558 update_vol_from_pool(ua, &mr);
561 update_all_vols_from_pool(ua, ua->argv[j]);
564 update_volenabled(ua, ua->argv[j], &mr);
567 update_vol_recyclepool(ua, ua->argv[j], &mr);
574 /* Allow user to simply update all volumes */
575 if (find_arg(ua, NT_("fromallpools")) > 0) {
581 start_prompt(ua, _("Parameters to modify:\n"));
582 add_prompt(ua, _("Volume Status")); /* 0 */
583 add_prompt(ua, _("Volume Retention Period")); /* 1 */
584 add_prompt(ua, _("Volume Use Duration")); /* 2 */
585 add_prompt(ua, _("Maximum Volume Jobs")); /* 3 */
586 add_prompt(ua, _("Maximum Volume Files")); /* 4 */
587 add_prompt(ua, _("Maximum Volume Bytes")); /* 5 */
588 add_prompt(ua, _("Recycle Flag")); /* 6 */
589 add_prompt(ua, _("Slot")); /* 7 */
590 add_prompt(ua, _("InChanger Flag")); /* 8 */
591 add_prompt(ua, _("Volume Files")); /* 9 */
592 add_prompt(ua, _("Pool")); /* 10 */
593 add_prompt(ua, _("Volume from Pool")); /* 11 */
594 add_prompt(ua, _("All Volumes from Pool")); /* 12 */
595 add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
596 add_prompt(ua, _("Enabled")), /* 14 */
597 add_prompt(ua, _("RecyclePool")), /* 15 */
598 add_prompt(ua, _("Done")); /* 16 */
599 i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
601 /* For All Volumes, All Volumes from Pool, and Done, we don't need
603 if ( i != 12 && i != 13 && i != 16) {
604 if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
607 ua->info_msg(_("Updating Volume \"%s\"\n"), mr.VolumeName);
610 case 0: /* Volume Status */
611 /* Modify Volume Status */
612 ua->info_msg(_("Current Volume status is: %s\n"), mr.VolStatus);
613 start_prompt(ua, _("Possible Values are:\n"));
614 add_prompt(ua, NT_("Append"));
615 add_prompt(ua, NT_("Archive"));
616 add_prompt(ua, NT_("Disabled"));
617 add_prompt(ua, NT_("Full"));
618 add_prompt(ua, NT_("Used"));
619 add_prompt(ua, NT_("Cleaning"));
620 if (strcmp(mr.VolStatus, NT_("Purged")) == 0) {
621 add_prompt(ua, NT_("Recycle"));
623 add_prompt(ua, NT_("Read-Only"));
624 if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
627 update_volstatus(ua, ua->cmd, &mr);
629 case 1: /* Retention */
630 ua->info_msg(_("Current retention period is: %s\n"),
631 edit_utime(mr.VolRetention, ed1, sizeof(ed1)));
632 if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
635 update_volretention(ua, ua->cmd, &mr);
638 case 2: /* Use Duration */
639 ua->info_msg(_("Current use duration is: %s\n"),
640 edit_utime(mr.VolUseDuration, ed1, sizeof(ed1)));
641 if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
644 update_voluseduration(ua, ua->cmd, &mr);
647 case 3: /* Max Jobs */
648 ua->info_msg(_("Current max jobs is: %u\n"), mr.MaxVolJobs);
649 if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
652 update_volmaxjobs(ua, ua->cmd, &mr);
655 case 4: /* Max Files */
656 ua->info_msg(_("Current max files is: %u\n"), mr.MaxVolFiles);
657 if (!get_pint(ua, _("Enter new Maximum Files: "))) {
660 update_volmaxfiles(ua, ua->cmd, &mr);
663 case 5: /* Max Bytes */
664 ua->info_msg(_("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
665 if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
668 update_volmaxbytes(ua, ua->cmd, &mr);
672 case 6: /* Recycle */
673 ua->info_msg(_("Current recycle flag is: %s\n"),
674 mr.Recycle==1?_("yes"):_("no"));
675 if (!get_yesno(ua, _("Enter new Recycle status: "))) {
678 update_volrecycle(ua, ua->cmd, &mr);
682 ua->info_msg(_("Current Slot is: %d\n"), mr.Slot);
683 if (!get_pint(ua, _("Enter new Slot: "))) {
686 update_volslot(ua, ua->cmd, &mr);
689 case 8: /* InChanger */
690 ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
691 bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
693 if (!get_yesno(ua, buf)) {
696 mr.InChanger = ua->pint32_val;
698 * Make sure to use db_update... rather than doing this directly,
699 * so that any Slot is handled correctly.
701 if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
702 ua->error_msg(_("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
704 ua->info_msg(_("New InChanger flag is: %d\n"), mr.InChanger);
709 case 9: /* Volume Files */
711 ua->warning_msg(_("Warning changing Volume Files can result\n"
712 "in loss of data on your Volume\n\n"));
713 ua->info_msg(_("Current Volume Files is: %u\n"), mr.VolFiles);
714 if (!get_pint(ua, _("Enter new number of Files for Volume: "))) {
717 VolFiles = ua->pint32_val;
718 if (VolFiles != (int)(mr.VolFiles + 1)) {
719 ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
720 if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
724 query = get_pool_memory(PM_MESSAGE);
725 Mmsg(query, "UPDATE Media SET VolFiles=%u WHERE MediaId=%s",
726 VolFiles, edit_int64(mr.MediaId, ed1));
727 if (!db_sql_query(ua->db, query, NULL, NULL)) {
728 ua->error_msg("%s", db_strerror(ua->db));
730 ua->info_msg(_("New Volume Files is: %u\n"), VolFiles);
732 free_pool_memory(query);
735 case 10: /* Volume's Pool */
736 memset(&pr, 0, sizeof(POOL_DBR));
737 pr.PoolId = mr.PoolId;
738 if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
739 ua->error_msg("%s", db_strerror(ua->db));
742 ua->info_msg(_("Current Pool is: %s\n"), pr.Name);
743 if (!get_cmd(ua, _("Enter new Pool name: "))) {
746 update_vol_pool(ua, ua->cmd, &mr, &pr);
750 update_vol_from_pool(ua, &mr);
753 pool = select_pool_resource(ua);
755 update_all_vols_from_pool(ua, pool->name());
764 ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
765 if (!get_cmd(ua, _("Enter new Enabled: "))) {
768 if (strcasecmp(ua->cmd, "yes") == 0 || strcasecmp(ua->cmd, "true") == 0) {
770 } else if (strcasecmp(ua->cmd, "no") == 0 || strcasecmp(ua->cmd, "false") == 0) {
772 } else if (strcasecmp(ua->cmd, "archived") == 0) {
775 mr.Enabled = atoi(ua->cmd);
777 update_volenabled(ua, ua->cmd, &mr);
781 memset(&pr, 0, sizeof(POOL_DBR));
782 pr.PoolId = mr.RecyclePoolId;
783 if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
784 ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
786 ua->info_msg(_("No current RecyclePool\n"));
788 if (!select_pool_dbr(ua, &pr, NT_("recyclepool"))) {
791 update_vol_recyclepool(ua, pr.Name, &mr);
794 default: /* Done or error */
795 ua->info_msg(_("Selection terminated.\n"));
803 * Update long term statistics
805 static bool update_stats(UAContext *ua)
807 int i = find_arg_with_value(ua, NT_("days"));
811 since = atoi(ua->argv[i]) * 24*60*60;
814 int nb = db_update_stats(ua->jcr, ua->db, since);
815 ua->info_msg(_("Updating %i job(s).\n"), nb);
821 * Update pool record -- pull info from current POOL resource
823 static bool update_pool(UAContext *ua)
831 pool = get_pool_resource(ua);
836 memset(&pr, 0, sizeof(pr));
837 bstrncpy(pr.Name, pool->name(), sizeof(pr.Name));
838 if (!get_pool_dbr(ua, &pr)) {
842 set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
843 set_pooldbr_recyclepoolid(ua->jcr, ua->db, &pr, pool);
845 id = db_update_pool_record(ua->jcr, ua->db, &pr);
847 ua->error_msg(_("db_update_pool_record returned %d. ERR=%s\n"),
848 id, db_strerror(ua->db));
850 query = get_pool_memory(PM_MESSAGE);
851 Mmsg(query, list_pool, edit_int64(pr.PoolId, ed1));
852 db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
853 free_pool_memory(query);
854 ua->info_msg(_("Pool DB record updated from resource.\n"));
859 * Update a Job record -- allows you to change the
860 * date fields in a Job record. This helps when
861 * providing migration from other vendors.
863 static bool update_job(UAContext *ua)
866 char ed1[50], ed2[50];
867 POOL_MEM cmd(PM_MESSAGE);
871 char *client_name = NULL;
872 char *start_time = NULL;
874 NT_("starttime"), /* 0 */
875 NT_("client"), /* 1 */
878 Dmsg1(200, "cmd=%s\n", ua->cmd);
879 i = find_arg_with_value(ua, NT_("jobid"));
881 ua->error_msg(_("Expect JobId keyword, not found.\n"));
884 memset(&jr, 0, sizeof(jr));
885 memset(&cr, 0, sizeof(cr));
886 jr.JobId = str_to_int64(ua->argv[i]);
887 if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
888 ua->error_msg("%s", db_strerror(ua->db));
892 for (i=0; kw[i]; i++) {
894 if ((j=find_arg_with_value(ua, kw[i])) >= 0) {
896 case 0: /* start time */
897 start_time = ua->argv[j];
899 case 1: /* Client name */
900 client_name = ua->argv[j];
905 if (!client_name && !start_time) {
906 ua->error_msg(_("Neither Client nor StartTime specified.\n"));
910 if (!get_client_dbr(ua, &cr)) {
913 jr.ClientId = cr.ClientId;
918 StartTime = str_to_utime(start_time);
919 if (StartTime == 0) {
920 ua->error_msg(_("Improper date format: %s\n"), ua->argv[i]);
923 delta_start = StartTime - jr.StartTime;
924 Dmsg3(200, "ST=%d jr.ST=%d delta=%d\n", (time_t)StartTime,
925 (time_t)jr.StartTime, (time_t)delta_start);
926 jr.StartTime = (time_t)StartTime;
927 jr.SchedTime += (time_t)delta_start;
928 jr.EndTime += (time_t)delta_start;
929 jr.JobTDate += delta_start;
930 /* Convert to DB times */
931 bstrutime(jr.cStartTime, sizeof(jr.cStartTime), jr.StartTime);
932 bstrutime(jr.cSchedTime, sizeof(jr.cSchedTime), jr.SchedTime);
933 bstrutime(jr.cEndTime, sizeof(jr.cEndTime), jr.EndTime);
935 Mmsg(cmd, "UPDATE Job SET ClientId=%s,StartTime='%s',SchedTime='%s',"
936 "EndTime='%s',JobTDate=%s WHERE JobId=%s",
937 edit_int64(jr.ClientId, ed1),
941 edit_uint64(jr.JobTDate, ed1),
942 edit_int64(jr.JobId, ed2));
943 if (!db_sql_query(ua->db, cmd.c_str(), NULL, NULL)) {
944 ua->error_msg("%s", db_strerror(ua->db));