]> git.sur5r.net Git - bacula/bacula/commitdiff
add Prune command -- not yet tested
authorKern Sibbald <kern@sibbald.com>
Mon, 29 Apr 2002 15:54:42 +0000 (15:54 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 29 Apr 2002 15:54:42 +0000 (15:54 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@9 91ce42f0-d328-0410-95d8-f526ca767f89

23 files changed:
bacula/src/cats/bdb_list.c
bacula/src/cats/make_mysql_tables.in
bacula/src/cats/sql.c
bacula/src/cats/sql_create.c
bacula/src/cats/sql_get.c
bacula/src/cats/sql_update.c
bacula/src/console.glade
bacula/src/dird/Makefile.in
bacula/src/dird/backup.c
bacula/src/dird/dird_conf.c
bacula/src/dird/ua.h
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_prune.c [new file with mode: 0644]
bacula/src/dird/ua_purge.c [new file with mode: 0644]
bacula/src/dird/ua_select.c
bacula/src/dird/ua_status.c
bacula/src/dird/verify.c
bacula/src/filed/status.c
bacula/src/lib/protos.h
bacula/src/lib/util.c
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/label.c

index 6cf95121151c95c2eab2d8dbd320aada1a2afdcd..36d22e73b92fe1b6ec8b7b5ee510bd762aca0081 100644 (file)
@@ -112,7 +112,7 @@ void db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit,
    len = sizeof(mr);
    while (fread(&mr, len, 1, mdb->mediafd) > 0) {
          Mmsg(&mdb->cmd, " %-10s %17s %-15s  %s\n",
-           mr.VolStatus, edit_uint_with_commas(mr.VolBytes, ewc),
+           mr.VolStatus, edit_uint64_with_commas(mr.VolBytes, ewc),
            mr.MediaType, mr.VolumeName);
         sendit(ctx, mdb->cmd);
    }
@@ -212,8 +212,8 @@ void db_list_job_records(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *
       strftime(dt, sizeof(dt), "%m-%d %H:%M", &tm);
       Mmsg(&mdb->cmd, " %7d  %-10s   %c    %c   %14s %10s  %c  %s\n", 
                ojr.JobId, dt, (char)ojr.Type, (char)ojr.Level, 
-               edit_uint_with_commas(ojr.JobBytes, ewc1), 
-               edit_uint_with_commas(ojr.JobFiles, ewc2),
+               edit_uint64_with_commas(ojr.JobBytes, ewc1), 
+               edit_uint64_with_commas(ojr.JobFiles, ewc2),
                (char)ojr.JobStatus, ojr.Name);
       sendit(ctx, mdb->cmd);
    }
@@ -253,9 +253,9 @@ void db_list_job_totals(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *c
       total_jobs++;
    }
    Mmsg(&mdb->cmd, " %7s  %10s   %15s\n", 
-            edit_uint_with_commas(total_jobs, ewc1),
-            edit_uint_with_commas(total_files, ewc2), 
-            edit_uint_with_commas(total_bytes, ewc3));
+            edit_uint64_with_commas(total_jobs, ewc1),
+            edit_uint64_with_commas(total_files, ewc2), 
+            edit_uint64_with_commas(total_bytes, ewc3));
    sendit(ctx, mdb->cmd);
    sendit(ctx, "=======================================\n");
    V(mdb->mutex);
index 0cf996e15f29efca86711ddff802a9c49bd7e4df..6ae35962fea385fcafd3cf7c728aad3350dcf878 100644 (file)
@@ -49,7 +49,7 @@ CREATE TABLE Job (
    SchedTime DATETIME NOT NULL,
    StartTime DATETIME NOT NULL,
    EndTime DATETIME NOT NULL,
-   StartDay INTEGER UNSIGNED NOT NULL,
+   StartDay BIGINT UNSIGNED NOT NULL,
    VolSessionId INTEGER UNSIGNED NOT NULL,
    VolSessionTime INTEGER UNSIGNED NOT NULL,
    JobFiles INTEGER UNSIGNED NOT NULL,
index c8436fa2d80ebd434467339e6f7cf26bbf1c349d..213cc4acf8f7c37b01eef178d9aa5f5c06f0634d 100644 (file)
@@ -79,7 +79,9 @@ InsertDB(char *file, int line, B_DB *mdb, char *cmd)
       mdb->num_rows = 1;
    }
    if (mdb->num_rows != 1) {
-      m_msg(file, line, &mdb->errmsg, _("Insertion problem: affect_rows=%" lld "\n"), mdb->num_rows);
+      char ed1[30];
+      m_msg(file, line, &mdb->errmsg, _("Insertion problem: affect_rows=%s\n"), 
+        edit_uint64(mdb->num_rows, ed1));
       e_msg(file, line, M_FATAL, 0, mdb->errmsg);  /* ***FIXME*** remove me */
       return 0;
    }
@@ -102,7 +104,9 @@ UpdateDB(char *file, int line, B_DB *mdb, char *cmd)
    }
    mdb->num_rows = sql_affected_rows(mdb);
    if (mdb->num_rows != 1) {
-      m_msg(file, line, &mdb->errmsg, _("Update problem: affect_rows=%" lld "\n"), mdb->num_rows);
+      char ed1[30];
+      m_msg(file, line, &mdb->errmsg, _("Update problem: affect_rows=%s\n"), 
+        edit_uint64(mdb->num_rows, ed1));
       e_msg(file, line, M_ERROR, 0, mdb->errmsg);
       e_msg(file, line, M_ERROR, 0, "%s\n", cmd);
       return 0;
index 82b6daebccd77a3713959e219d000b46adebddc3..129e96249890089625971d1cea61f63428a7432e 100644 (file)
@@ -68,13 +68,14 @@ db_create_job_record(B_DB *mdb, JOB_DBR *jr)
    struct tm tm;
    int stat;
    char *JobId;
-   int32_t StartDay;
+   btime_t StartDay;
+   char ed1[30];
 
    stime = jr->SchedTime;
 
    localtime_r(&stime, &tm); 
    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
-   StartDay = (int32_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+   StartDay = (btime_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
        date_encode(2000, 1, 1));
 
    P(mdb->mutex);
@@ -87,9 +88,9 @@ db_create_job_record(B_DB *mdb, JOB_DBR *jr)
    /* Must create it */
    Mmsg(&mdb->cmd,
 "INSERT INTO Job (JobId, Job, Name, Type, Level, SchedTime, StartDay) VALUES \
-(%s, \"%s\", \"%s\", \"%c\", \"%c\", \"%s\", %d)", 
+(%s, \"%s\", \"%s\", \"%c\", \"%c\", \"%s\", %s)", 
           JobId, jr->Job, jr->Name, (char)(jr->Type), (char)(jr->Level), dt,
-          StartDay);
+          edit_uint64(StartDay, ed1));
 
    if (!INSERT_DB(mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"), 
@@ -212,6 +213,7 @@ int
 db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
 {
    int stat;
+   char ed1[30], ed2[30];
 
    P(mdb->mutex);
    Mmsg(&mdb->cmd, "SELECT MediaId FROM Media WHERE VolumeName=\"%s\"", 
@@ -232,10 +234,11 @@ db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
    /* Must create it */
    Mmsg(&mdb->cmd, 
 "INSERT INTO Media (VolumeName, MediaType, PoolId, VolMaxBytes, VolCapacityBytes, \
-VolStatus, Recycle) VALUES (\"%s\", \"%s\", %d, %" lld ", %" lld ", \"%s\", \"%s\")", 
+VolStatus, Recycle) VALUES (\"%s\", \"%s\", %d, %s, %s, \"%s\", \"%s\")", 
                  mr->VolumeName,
                  mr->MediaType, mr->PoolId, 
-                 mr->VolMaxBytes, mr->VolCapacityBytes, 
+                 edit_uint64(mr->VolMaxBytes,ed1),
+                 edit_uint64(mr->VolCapacityBytes, ed2),
                  mr->VolStatus, mr->Recycle);
 
    if (!INSERT_DB(mdb, mdb->cmd)) {
@@ -550,8 +553,9 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
       mdb->num_rows = sql_num_rows(mdb);
 
       if (mdb->num_rows > 1) {
-         Mmsg2(&mdb->errmsg, _("More than one Path!: %" lld " for Path=%s\n"), 
-           mdb->num_rows, path);
+        char ed1[30];
+         Mmsg2(&mdb->errmsg, _("More than one Path!: %s for Path=%s\n"), 
+           edit_uint64(mdb->num_rows, ed1), path);
          Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
          Emsg1(M_ERROR, 0, "%s\n", mdb->cmd);
       }
index a50a17925930cd9d51a0bf8ea314ba5a330fac2b..c0e27e54e6051ee5cceb27540c404467d32af7d8 100644 (file)
@@ -232,11 +232,12 @@ static int db_get_path_record(B_DB *mdb, char *path)
    Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path=\"%s\"", path);
 
    if (QUERY_DB(mdb, mdb->cmd)) {
-
+      char ed1[30];
       mdb->num_rows = sql_num_rows(mdb);
 
       if (mdb->num_rows > 1) {
-         Mmsg1(&mdb->errmsg, _("More than one Path!: %" lld "\n"), mdb->num_rows);
+         Mmsg1(&mdb->errmsg, _("More than one Path!: %s\n"), 
+           edit_uint64(mdb->num_rows, ed1));
         Emsg0(M_FATAL, 0, mdb->errmsg);
       } else if (mdb->num_rows == 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
@@ -433,7 +434,9 @@ PoolType, LabelFormat FROM Pool WHERE Pool.Name=\"%s\"", pdbr->Name);
    if (QUERY_DB(mdb, mdb->cmd)) {
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
-         Mmsg1(&mdb->errmsg, _("More than one Pool!: %" lld "\n"), mdb->num_rows);
+        char ed1[30];
+         Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"), 
+           edit_uint64(mdb->num_rows, ed1));
         Emsg0(M_ERROR, 0, mdb->errmsg);
       } else if (mdb->num_rows == 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
@@ -550,7 +553,9 @@ FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName);
    if (QUERY_DB(mdb, mdb->cmd)) {
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
-         Mmsg1(&mdb->errmsg, _("More than one Volume!: %" lld "\n"), mdb->num_rows);
+        char ed1[30];
+         Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"), 
+           edit_uint64(mdb->num_rows, ed1));
         Emsg0(M_ERROR, 0, mdb->errmsg);
       } else if (mdb->num_rows == 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
@@ -574,6 +579,8 @@ FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName);
            mr->PoolId = atoi(row[13]);
            stat = mr->MediaId;
         }
+      } else {
+         Mmsg0(&mdb->errmsg, _("Media record not found.\n"));
       }
       sql_free_result(mdb);
    }
index 4a2183a63c9fcebfad4110a056b694b3ea24173b..1b6d2dbfcedfe777b06e7ec82361c40edc1793e1 100644 (file)
@@ -100,19 +100,20 @@ db_update_job_start_record(B_DB *mdb, JOB_DBR *jr)
    char dt[MAX_TIME_LENGTH];
    time_t stime;
    struct tm tm;
-   int32_t StartDay;
+   btime_t StartDay;
    int stat;
+   char ed1[30];
        
    stime = jr->StartTime;
    localtime_r(&stime, &tm);
    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
-   StartDay = (int32_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+   StartDay = (btime_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
        date_encode(2000, 1, 1));
 
    P(mdb->mutex);
    Mmsg(&mdb->cmd, "UPDATE Job SET Level='%c', StartTime=\"%s\", \
-ClientId=%d, StartDay=%d WHERE JobId=%d",
-      (char)(jr->Level), dt, jr->ClientId, StartDay, jr->JobId);
+ClientId=%d, StartDay=%s WHERE JobId=%d",
+      (char)(jr->Level), dt, jr->ClientId, edit_uint64(StartDay, ed1), jr->JobId);
    stat = UPDATE_DB(mdb, mdb->cmd);
    V(mdb->mutex);
    return stat;
@@ -133,19 +134,23 @@ db_update_job_end_record(B_DB *mdb, JOB_DBR *jr)
    time_t ttime;
    struct tm tm;
    int stat;
+   char ed1[30], ed2[30];
+   btime_t StartDay;
        
    ttime = jr->EndTime;
    localtime_r(&ttime, &tm);
    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
+   StartDay = (btime_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+       date_encode(2000, 1, 1));
 
    P(mdb->mutex);
    Mmsg(&mdb->cmd,
       "UPDATE Job SET JobStatus='%c', EndTime='%s', \
-ClientId=%d, JobBytes=%" lld ", JobFiles=%d, JobErrors=%d, VolSessionId=%d, \
-VolSessionTime=%d, PoolId=%d, FileSetId=%d WHERE JobId=%d",
-      (char)(jr->JobStatus), dt, jr->ClientId, jr->JobBytes, jr->JobFiles,
-      jr->JobErrors, jr->VolSessionId, jr->VolSessionTime, 
-      jr->PoolId, jr->FileSetId, jr->JobId);
+ClientId=%d, JobBytes=%s, JobFiles=%d, JobErrors=%d, VolSessionId=%d, \
+VolSessionTime=%d, PoolId=%d, FileSetId=%d, StartDay=%s WHERE JobId=%d",
+      (char)(jr->JobStatus), dt, jr->ClientId, edit_uint64(jr->JobBytes, ed1), 
+      jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime, 
+      jr->PoolId, jr->FileSetId, edit_uint64(StartDay, ed2), jr->JobId);
 
    stat = UPDATE_DB(mdb, mdb->cmd);
    V(mdb->mutex);
@@ -183,6 +188,7 @@ db_update_media_record(B_DB *mdb, MEDIA_DBR *mr)
    time_t ttime;
    struct tm tm;
    int stat;
+   char ed1[30], ed2[30];
        
    ttime = mr->LastWritten;
    localtime_r(&ttime, &tm);
@@ -199,12 +205,13 @@ db_update_media_record(B_DB *mdb, MEDIA_DBR *mr)
    }
 
    Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%d,\
- VolFiles=%d, VolBlocks=%d, VolBytes=%" lld ", VolMounts=%d, VolErrors=%d,\
- VolWrites=%d, VolMaxBytes=%" lld ", LastWritten=\"%s\", VolStatus=\"%s\" \
+ VolFiles=%d, VolBlocks=%d, VolBytes=%s, VolMounts=%d, VolErrors=%d,\
+ VolWrites=%d, VolMaxBytes=%s, LastWritten=\"%s\", VolStatus=\"%s\" \
  WHERE VolumeName=\"%s\"",
-   mr->VolJobs, mr->VolFiles, mr->VolBlocks, mr->VolBytes, mr->VolMounts,
-   mr->VolErrors, mr->VolWrites, mr->VolMaxBytes, dt, mr->VolStatus,
-   mr->VolumeName);
+   mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
+   mr->VolMounts, mr->VolErrors, mr->VolWrites, 
+   edit_uint64(mr->VolMaxBytes, ed2), dt, 
+   mr->VolStatus, mr->VolumeName);
 
    stat = UPDATE_DB(mdb, mdb->cmd);
    V(mdb->mutex);
index e0ba0711948a27edf7da43c7580352f4bc2788a6..5a7fa1c3ec3dd7c820a85b63860d14f6e4e2cf13 100644 (file)
   <output_build_files>False</output_build_files>
 </project>
 
-<widget>
-  <class>GnomeAbout</class>
-  <name>about</name>
-  <visible>False</visible>
-  <modal>True</modal>
-  <copyright>Copyright (c) 1999 - 2002, Kern Sibbald and John Walker</copyright>
-  <authors>Kern Sibbald and John Walker
-</authors>
-  <comments>It comes by night and sucks the essence from your computers.</comments>
-</widget>
-
 <widget>
   <class>GnomeMessageBox</class>
   <name>messagebox1</name>
   </widget>
 </widget>
 
+<widget>
+  <class>GtkDialog</class>
+  <name>about1</name>
+  <width>382</width>
+  <height>242</height>
+  <title>About Bacula Console</title>
+  <type>GTK_WINDOW_TOPLEVEL</type>
+  <position>GTK_WIN_POS_CENTER</position>
+  <modal>True</modal>
+  <allow_shrink>False</allow_shrink>
+  <allow_grow>False</allow_grow>
+  <auto_shrink>False</auto_shrink>
+
+  <widget>
+    <class>GtkVBox</class>
+    <child_name>Dialog:vbox</child_name>
+    <name>dialog-vbox5</name>
+    <homogeneous>False</homogeneous>
+    <spacing>0</spacing>
+
+    <widget>
+      <class>GtkHBox</class>
+      <child_name>Dialog:action_area</child_name>
+      <name>dialog-action_area5</name>
+      <border_width>10</border_width>
+      <homogeneous>True</homogeneous>
+      <spacing>5</spacing>
+      <child>
+       <padding>0</padding>
+       <expand>False</expand>
+       <fill>True</fill>
+       <pack>GTK_PACK_END</pack>
+      </child>
+
+      <widget>
+       <class>GtkHBox</class>
+       <name>hbox20</name>
+       <homogeneous>False</homogeneous>
+       <spacing>0</spacing>
+       <child>
+         <padding>0</padding>
+         <expand>True</expand>
+         <fill>True</fill>
+       </child>
+
+       <widget>
+         <class>GtkLabel</class>
+         <name>label44</name>
+         <label></label>
+         <justify>GTK_JUSTIFY_CENTER</justify>
+         <wrap>False</wrap>
+         <xalign>0.5</xalign>
+         <yalign>0.5</yalign>
+         <xpad>0</xpad>
+         <ypad>0</ypad>
+         <child>
+           <padding>0</padding>
+           <expand>True</expand>
+           <fill>False</fill>
+         </child>
+       </widget>
+
+       <widget>
+         <class>GtkButton</class>
+         <name>about_button</name>
+         <border_width>1</border_width>
+         <width>80</width>
+         <can_default>True</can_default>
+         <can_focus>True</can_focus>
+         <signal>
+           <name>clicked</name>
+           <handler>on_about_button_clicked</handler>
+           <last_modification_time>Sun, 28 Apr 2002 15:55:15 GMT</last_modification_time>
+         </signal>
+         <stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
+         <relief>GTK_RELIEF_NORMAL</relief>
+         <child>
+           <padding>0</padding>
+           <expand>False</expand>
+           <fill>False</fill>
+         </child>
+       </widget>
+      </widget>
+    </widget>
+
+    <widget>
+      <class>GtkVBox</class>
+      <name>vbox8</name>
+      <homogeneous>False</homogeneous>
+      <spacing>0</spacing>
+      <child>
+       <padding>0</padding>
+       <expand>True</expand>
+       <fill>True</fill>
+      </child>
+
+      <widget>
+       <class>GtkVBox</class>
+       <name>vbox9</name>
+       <homogeneous>False</homogeneous>
+       <spacing>0</spacing>
+       <child>
+         <padding>0</padding>
+         <expand>True</expand>
+         <fill>True</fill>
+       </child>
+
+       <widget>
+         <class>GtkLabel</class>
+         <name>about_head</name>
+         <height>102</height>
+         <label>Bacula Console 1.19 (28 April 2002)
+</label>
+         <justify>GTK_JUSTIFY_CENTER</justify>
+         <wrap>False</wrap>
+         <xalign>0.5</xalign>
+         <yalign>0.5</yalign>
+         <xpad>0</xpad>
+         <ypad>0</ypad>
+         <child>
+           <padding>0</padding>
+           <expand>False</expand>
+           <fill>False</fill>
+         </child>
+       </widget>
+
+       <widget>
+         <class>GtkHSeparator</class>
+         <name>hseparator1</name>
+         <child>
+           <padding>0</padding>
+           <expand>False</expand>
+           <fill>False</fill>
+         </child>
+       </widget>
+
+       <widget>
+         <class>GtkLabel</class>
+         <name>copyright</name>
+         <label>Copyright (c) 1999 - 2002, Kern Sibbald and John Walker</label>
+         <justify>GTK_JUSTIFY_LEFT</justify>
+         <wrap>False</wrap>
+         <xalign>0.1</xalign>
+         <yalign>0.5</yalign>
+         <xpad>0</xpad>
+         <ypad>0</ypad>
+         <child>
+           <padding>0</padding>
+           <expand>True</expand>
+           <fill>False</fill>
+         </child>
+       </widget>
+
+       <widget>
+         <class>GtkLabel</class>
+         <name>authors</name>
+         <label>Authors: Kern Sibbald and John Walker</label>
+         <justify>GTK_JUSTIFY_LEFT</justify>
+         <wrap>False</wrap>
+         <xalign>0.0400001</xalign>
+         <yalign>0.5</yalign>
+         <xpad>0</xpad>
+         <ypad>0</ypad>
+         <child>
+           <padding>0</padding>
+           <expand>True</expand>
+           <fill>False</fill>
+         </child>
+       </widget>
+
+       <widget>
+         <class>GtkLabel</class>
+         <name>theme</name>
+         <label>It comes by night and sucks the essence from your computers</label>
+         <justify>GTK_JUSTIFY_LEFT</justify>
+         <wrap>False</wrap>
+         <xalign>0.15</xalign>
+         <yalign>0.5</yalign>
+         <xpad>0</xpad>
+         <ypad>0</ypad>
+         <child>
+           <padding>0</padding>
+           <expand>True</expand>
+           <fill>False</fill>
+         </child>
+       </widget>
+      </widget>
+    </widget>
+  </widget>
+</widget>
+
 </GTK-Interface>
index fa96686e51e4104f6e752f4ff329954988ba63e1..a7aeaf24b37a064d1415d876475f033027e6089f 100644 (file)
@@ -20,22 +20,28 @@ first_rule: all
 dummy:
 
 #
-SVRSRCS = dird.c authenticate.c backup.c catreq.c dird_conf.c \
+SVRSRCS = dird.c authenticate.c backup.c \
+         catreq.c dird_conf.c \
          fd_cmds.c getmsg.c job.c \
-         mountreq.c msgchan.c newvol.c run_conf.c restore.c \
+         mountreq.c msgchan.c newvol.c \
+         run_conf.c restore.c \
          scheduler.c ua_cmds.c \
          ua_dotcmds.c \
          ua_db_query.c ua_retention.c \
-         ua_input.c ua_output.c ua_prune.c ua_run.c \
+         ua_input.c ua_output.c ua_prune.c \
+         ua_purge.c ua_run.c \
          ua_select.c ua_server.c \
          ua_status.c verify.c
-SVROBJS = dird.o authenticate.o backup.o catreq.o dird_conf.o \
+SVROBJS = dird.o authenticate.o backup.o \
+         catreq.o dird_conf.o \
          fd_cmds.o getmsg.o job.o \
-         mountreq.o msgchan.o newvol.o run_conf.o restore.o \
+         mountreq.o msgchan.o newvol.o \
+         run_conf.o restore.o \
          scheduler.o ua_cmds.o \
          ua_dotcmds.o \
          ua_db_query.o ua_retention.o \
-         ua_input.o ua_output.o ua_prune.o ua_run.o \
+         ua_input.o ua_output.o ua_prune.o \
+         ua_purge.o ua_run.o \
          ua_select.o ua_server.o \
          ua_status.o verify.o
 
index 3d5c4c239c2e63176d9fc8098888cd9602f3c40d..7d6950d7cc841b3ba6be247bd747691520d30eb4 100644 (file)
@@ -432,12 +432,12 @@ Termination:            %s\n"),
        jcr->client->hdr.name,
        sdt,
        edt,
-       edit_uint_with_commas(jcr->jr.JobBytes, ec1),
-       edit_uint_with_commas(jcr->jr.JobFiles, ec2),
+       edit_uint64_with_commas(jcr->jr.JobBytes, ec1),
+       edit_uint64_with_commas(jcr->jr.JobFiles, ec2),
        jcr->VolumeName,
        jcr->VolSessionId,
        jcr->VolSessionTime,
-       edit_uint_with_commas(mr.VolBytes, ec3),
+       edit_uint64_with_commas(mr.VolBytes, ec3),
        term_msg);
 
    Dmsg0(100, "Leave backup_cleanup()\n");
index fbf4e4e8288cff1fdab8514373f547ca995cd95f..e59dcaf3266aab13395e0039277b0d4edd924594 100644 (file)
@@ -358,10 +358,11 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...
    }
    switch (type) {
       case R_DIRECTOR:
-         sendit(sock, "Director: name=%s maxjobs=%d FDtimeout=%" lld " SDtimeout=%" lld "\n", 
+        char ed1[30], ed2[30];
+         sendit(sock, "Director: name=%s maxjobs=%d FDtimeout=%s SDtimeout=%s\n", 
            reshdr->name, res->res_dir.MaxConcurrentJobs, 
-           res->res_dir.FDConnectTimeout,
-           res->res_dir.SDConnectTimeout);
+           edit_uint64(res->res_dir.FDConnectTimeout, ed1),
+           edit_uint64(res->res_dir.SDConnectTimeout, ed2));
         if (res->res_dir.query_file) {
             sendit(sock, "   query_file=%s\n", res->res_dir.query_file);
         }
index d9f41204d89d0cf2fdea7f546b988282a809fd4b..28e979949123a90f2d3191c5eed8e3cf3280c180 100644 (file)
@@ -31,17 +31,17 @@ typedef struct s_ua_context {
    JCR *jcr;
    B_DB *db;
    CAT *catalog;
-   char *cmd;                         /* return command/name buffer */
-   char *args;                        /* command line arguments */
-   char *argk[MAX_ARGS];              /* argument keywords */
-   char *argv[MAX_ARGS];              /* argument values */
-   int argc;                          /* number of arguments */
-   char **prompt;                     /* list of prompts */
-   int max_prompts;                   /* max size of list */
-   int num_prompts;                   /* current number in list */
-   int auto_display_messages;         /* if set, display messages */
+   char *cmd;                        /* return command/name buffer */
+   char *args;                       /* command line arguments */
+   char *argk[MAX_ARGS];             /* argument keywords */
+   char *argv[MAX_ARGS];             /* argument values */
+   int argc;                         /* number of arguments */
+   char **prompt;                    /* list of prompts */
+   int max_prompts;                  /* max size of list */
+   int num_prompts;                  /* current number in list */
+   int auto_display_messages;        /* if set, display messages */
    int user_notified_msg_pending;     /* set when user notified */
-   int automount;                     /* if set, mount after label */
+   int automount;                    /* if set, mount after label */
 } UAContext;
 
 /* ua_cmds.c */
@@ -68,16 +68,18 @@ JOB   *select_job_resource(UAContext *ua);
 int    select_pool_dbr(UAContext *ua, POOL_DBR *pr);
 CLIENT *select_client_resource(UAContext *ua);
 FILESET *select_fs_resource(UAContext *ua);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
 
 void   start_prompt(UAContext *ua, char *msg);
 void   add_prompt(UAContext *ua, char *prompt);
 int    do_prompt(UAContext *ua, char *msg, char *prompt);
-CAT   *get_catalog_resource(UAContext *ua);           
+CAT   *get_catalog_resource(UAContext *ua);          
 STORE *get_storage_resource(UAContext *ua, char *cmd);
 int    get_media_type(UAContext *ua, char *MediaType);
 int    get_pool_dbr(UAContext *ua, POOL_DBR *pr);
 POOL  *get_pool_resource(UAContext *ua);
 CLIENT *get_client_resource(UAContext *ua);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
 
 int find_arg_keyword(UAContext *ua, char **list);
 int do_keyword_prompt(UAContext *ua, char *msg, char **list);
index 63c43b7ec3d33c219b46236348cc8a0bdad7119c..f2b137a375137ba4fc51c7839b641e3135d6c1a4 100644 (file)
@@ -51,6 +51,7 @@ extern int querycmd(UAContext *ua, char *cmd);
 extern int runcmd(UAContext *ua, char *cmd);
 extern int retentioncmd(UAContext *ua, char *cmd);
 extern int prunecmd(UAContext *ua, char *cmd);
+extern int purgecmd(UAContext *ua, char *cmd);
 
 /* Forward referenced functions */
 static int addcmd(UAContext *ua, char *cmd),  createcmd(UAContext *ua, char *cmd), cancelcmd(UAContext *ua, char *cmd);
@@ -82,6 +83,7 @@ static struct cmdstruct commands[] = {
  { N_("messages"),   messagescmd,  _("messages")},
  { N_("mount"),      mountcmd,     _("mount <storage-name>")},
  { N_("prune"),      prunecmd,     _("prune expired records from catalog")},
+ { N_("purge"),      purgecmd,     _("purge records from catalog")},
  { N_("run"),        runcmd,       _("run <job-name>")},
  { N_("setdebug"),   setdebugcmd,  _("sets debug level")},
  { N_("show"),       showcmd,      _("show (resource records) [jobs | pools | ... | all]")},
@@ -926,37 +928,13 @@ static int delete_media(UAContext *ua)
 {
    POOL_DBR pr;
    MEDIA_DBR mr;
-   int found = FALSE;
-   int i;
 
-   memset(&pr, 0, sizeof(pr));
-   memset(&mr, 0, sizeof(mr));
-
-   /* Get the pool, possibly from pool=<pool-name> */
-   if (!get_pool_dbr(ua, &pr)) {
+   if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
       return 1;
    }
-   mr.PoolId = pr.PoolId;
-
-   /* See if a volume name is specified as an argument */
-   for (i=1; i<ua->argc; i++) {
-      if (strcasecmp(ua->argk[i], _("volume")) == 0 && ua->argv[i]) {
-        found = TRUE;
-        break;
-      }
-   }
-   if (found) {
-      strcpy(mr.VolumeName, ua->argv[i]);
-   } else {
-      db_list_media_records(ua->db, &mr, prtit, ua);
-      if (!get_cmd(ua, _("Enter the Volume name to delete: "))) {
-        return 1;
-      }
-   }
-   mr.MediaId = 0;
-   strcpy(mr.VolumeName, ua->cmd);
    bsendmsg(ua, _("\nThis command will delete volume %s\n"
-      "and all Jobs saved on that volume from the Catalog\n"));
+      "and all Jobs saved on that volume from the Catalog\n"),
+      mr.VolumeName);
 
    if (!get_cmd(ua, _("If you want to continue enter pretty please: "))) {
       return 1;
diff --git a/bacula/src/dird/ua_prune.c b/bacula/src/dird/ua_prune.c
new file mode 100644 (file)
index 0000000..389ac44
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ *
+ *   Bacula Director -- User Agent Database prune Command
+ *     Applies retention periods
+ *
+ *     Kern Sibbald, February MMII
+ */
+
+/*
+   Copyright (C) 2002 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "dird.h"
+#include "ua.h"
+
+/* Forward referenced functions */
+int prune_files(UAContext *ua, CLIENT *client);
+int prune_jobs(UAContext *ua, CLIENT *client);
+int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+
+
+#define MAX_DEL_LIST_LEN 1000000
+
+/*
+ * Select JobIds for File deletion.
+ */
+static char *select_job =
+   "SELECT JobId from Job "    
+   "WHERE StartDay < %s "
+   "AND ClientId=%d "
+   "AND PurgedFiles=0";
+
+/*
+ * List of SQL commands terminated by NULL for deleting
+ *  temporary tables and indicies 
+ */
+static char *drop_deltabs[] = {
+   "DROP TABLE DelCandidates",
+   "DROP INDEX DelInx1",
+   NULL};
+
+/*
+ * List of SQL commands to create temp table and indicies
+ */
+static char *create_deltabs[] = {
+   "CREATE TABLE DelCandidates ("
+      "JobId INTEGER UNSIGNED NOT NULL, "
+      "PurgedFiles TINYINT, "
+      "FileSetId INTEGER UNSIGNED)",
+   "CREATE INDEX DelInx1 ON DelCandidates (JobId)",
+   NULL};
+
+
+/*
+ * Fill candidates table with all Files subject to being deleted
+ */
+static char *insert_delcand = 
+   "INSERT INTO DelCandidates "
+   "SELECT JobId, PurgedFiles, FileSetId FROM Job "
+   "WHERE StartDay < %s " 
+   "AND ClientId=%d";
+
+/*
+ * Select files from the DelCandidates table that have a
+ * more recent backup -- i.e. are not the only backup.
+ * This is the list of files to delete.
+ */
+static char *select_del =
+   "SELECT DelCandidates.JobId "
+   "FROM Job,DelCandidates "
+   "WHERE Job.StartDay >= %s "
+   "AND Job.ClientId=%d "
+   "AND Job.Level='F' "
+   "AND Job.JobStatus='T' "
+   "AND Job.FileSetId=DelCandidates.FileSetId";
+
+/* In memory list of JobIds */
+struct s_file_del_ctx {
+   JobId_t *JobId;
+   int num_ids;                      /* ids stored */
+   int max_ids;                      /* size of array */
+   int num_del;                      /* number deleted */
+   int tot_ids;                      /* total to process */
+};
+
+struct s_job_del_ctx {
+   JobId_t *JobId;                   /* array of JobIds */
+   char *PurgedFiles;                /* Array of PurgedFile flags */
+   int num_ids;                      /* ids stored */
+   int max_ids;                      /* size of array */
+   int num_del;                      /* number deleted */
+   int tot_ids;                      /* total to process */
+};
+
+struct s_count_ctx {
+   int count;
+};
+
+
+/*
+ * Called here to count entries to be deleted 
+ */
+static int count_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_count_ctx *cnt = (struct s_count_ctx *)ctx;
+
+   if (row[0]) {
+      cnt->count = atoi(row[0]);
+   } else {
+      cnt->count = 0;
+   }
+   return 0;
+}
+
+
+/*
+ * Called here to count entries to be deleted 
+ */
+static int file_count_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+   del->tot_ids++;
+   return 0;
+}
+
+
+/*
+ * Called here to make in memory list of JobIds to be
+ *  deleted and the associated PurgedFiles flag.
+ *  The in memory list will then be transversed
+ *  to issue the SQL DELETE commands.  Note, the list
+ *  is allowed to get to MAX_DEL_LIST_LEN to limit the
+ *  maximum malloc'ed memory.
+ */
+static int job_delete_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx;
+
+   if (del->num_ids == MAX_DEL_LIST_LEN) {  
+      return 1;
+   }
+   if (del->num_ids == del->max_ids) {
+      del->max_ids = (del->max_ids * 3) / 2;
+      del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids);
+      del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids);
+   }
+   del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL);
+   del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]);
+   return 0;
+}
+
+static int file_delete_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+
+   if (del->num_ids == MAX_DEL_LIST_LEN) {  
+      return 1;
+   }
+   if (del->num_ids == del->max_ids) {
+      del->max_ids = (del->max_ids * 3) / 2;
+      del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
+        del->max_ids);
+   }
+   del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+   return 0;
+}
+
+/*
+ *   Prune records from database
+ */
+int prunecmd(UAContext *ua, char *cmd)
+{
+   CLIENT *client;
+   POOL_DBR pr;
+   MEDIA_DBR mr;
+
+   static char *keywords[] = {
+      N_("files"),
+      N_("jobs"),
+      N_("volume"),
+      NULL};
+   if (!open_db(ua)) {
+      return 1;
+   }
+   switch (find_arg_keyword(ua, keywords)) {
+   case 0:
+      client = select_client_resource(ua);
+      prune_files(ua, client);
+      return 1;
+   case 1:
+      client = select_client_resource(ua);
+      prune_jobs(ua, client);
+      return 1;
+   case 2:
+      if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
+        return 1;
+      }
+      prune_volume(ua, &pr, &mr);
+      return 1;
+   default:
+      break;
+   }
+   switch (do_keyword_prompt(ua, _("Choose item to prune"), keywords)) {
+   case 0:
+      client = select_client_resource(ua);
+      if (!client) {
+        return 1;
+      }
+      prune_files(ua, client);
+      break;
+   case 1:
+      client = select_client_resource(ua);
+      if (!client) {
+        return 1;
+      }
+      prune_jobs(ua, client);
+      break;
+   case 2:
+      if (!select_pool_and_media_dbr(ua, &pr, &mr)) {
+        return 1;
+      }
+      prune_volume(ua, &pr, &mr);
+      return 1;
+   }
+   return 1;
+}
+
+/*
+ * Prune File records from the database. For any Job which
+ * is older than the retention period, we unconditionally delete
+ * all File records for that Job.  This is simple enough that no
+ * temporary tables are needed. We simply make an in memory list of
+ * the JobIds meeting the prune conditions, then delete all File records
+ * pointing to each of those JobIds.
+ */
+int prune_files(UAContext *ua, CLIENT *client)
+{
+   struct s_file_del_ctx del;
+   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   int i;
+   struct tm tm;
+   uint64_t today, period;
+   time_t now;
+   CLIENT_DBR cr;
+   char ed1[50];
+
+   memset(&cr, 0, sizeof(cr));
+   strcpy(cr.Name, client->hdr.name);
+   if (!db_create_client_record(ua->db, &cr)) {
+      return 0;
+   }
+
+   period = client->FileRetention;
+   now = time(NULL);
+   localtime_r(&now, &tm);
+   today = (uint64_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+       date_encode(2000, 1, 1));
+       
+   del.JobId = NULL;
+   del.num_ids = 0;
+   del.tot_ids = 0;
+   del.num_del = 0;
+   del.max_ids = 0;
+
+   Dmsg3(100, "Today=%d period=%d period=%d\n", (uint32_t)today, (uint32_t)period,          
+      (uint32_t)(period/(3600*24)));
+
+   Mmsg(&query, select_job, 
+       edit_uint64(today - period/(3600*24), ed1), cr.ClientId);
+
+   Dmsg1(050, "select sql=%s\n", query);
+   if (!db_sql_query(ua->db, query, file_count_handler, (void *)&del)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      Dmsg0(050, "Count failed\n");
+      goto bail_out;
+   }
+      
+   if (del.tot_ids == 0) {
+      bsendmsg(ua, _("No Files found for client %s to prune from %s catalog.\n"),
+        client->hdr.name, client->catalog->hdr.name);
+      goto bail_out;
+   }
+
+   if (del.tot_ids < MAX_DEL_LIST_LEN) {
+      del.max_ids = del.tot_ids + 1;
+   } else {
+      del.max_ids = MAX_DEL_LIST_LEN; 
+   }
+   del.tot_ids = 0;
+
+   del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+
+   db_sql_query(ua->db, query, file_delete_handler, (void *)&del);
+
+   for (i=0; i < del.num_ids; i++) {
+      Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+      Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      /* 
+       * Now mark Job as having files purged. This is necessary to
+       * avoid having too many Jobs to process in future prunings. If
+       * we don't do this, the number of JobId's in our in memory list
+       * will grow very large.
+       */
+      Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      Dmsg1(050, "Del sql=%s\n", query);
+   }
+   bsendmsg(ua, _("%d Files for client %s pruned from %s catalog.\n"), del.num_ids,
+      client->hdr.name, client->catalog->hdr.name);
+   
+bail_out:
+   if (del.JobId) {
+      free(del.JobId);
+   }
+   free_pool_memory(query);
+   return 1;
+}
+
+
+static void drop_temp_tables(UAContext *ua) 
+{
+   int i;
+   for (i=0; drop_deltabs[i]; i++) {
+      db_sql_query(ua->db, drop_deltabs[i], NULL, (void *)NULL);
+   }
+}
+
+static int create_temp_tables(UAContext *ua) 
+{
+   int i;
+   /* Create temp tables and indicies */
+   for (i=0; create_deltabs[i]; i++) {
+      if (!db_sql_query(ua->db, create_deltabs[i], NULL, (void *)NULL)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+         Dmsg0(050, "create DelTables table failed\n");
+        return 0;
+      }
+   }
+   return 1;
+}
+
+
+
+/*
+ * Purging Jobs is a bit more complicated than purging Files
+ * because we delete Job records only if there is a more current
+ * backup of the FileSet. Otherwise, we keep the Job record.
+ * In other words, we never delete the only Job record that
+ * contains a current backup of a FileSet. This prevents the
+ * Volume from being recycled and destroying a current backup.
+ */
+int prune_jobs(UAContext *ua, CLIENT *client)
+{
+   struct s_job_del_ctx del;
+   struct s_count_ctx cnt;
+   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   int i;
+   struct tm tm;
+   uint64_t today, period;
+   time_t now;
+   CLIENT_DBR cr;
+   char ed1[50];
+
+   memset(&cr, 0, sizeof(cr));
+   strcpy(cr.Name, client->hdr.name);
+   if (!db_create_client_record(ua->db, &cr)) {
+      return 0;
+   }
+
+   period = client->JobRetention;
+   now = time(NULL);
+   localtime_r(&now, &tm);
+   today = (uint64_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
+       date_encode(2000, 1, 1));
+       
+
+   del.JobId = NULL;
+   del.num_ids = 0;
+   del.tot_ids = 0;
+   del.num_del = 0;
+   del.max_ids = 0;
+
+   Dmsg3(050, "Today=%d period=%d period=%d\n", (uint32_t)today, (uint32_t)period,          
+      (uint32_t)(period/(3600*24)));
+
+   /* Drop any previous temporary tables still there */
+   drop_temp_tables(ua);
+
+   /* Create temp tables and indicies */
+   if (!create_temp_tables(ua)) {
+      goto bail_out;
+   }
+
+   /* 
+    * Select all files that are older than the JobRetention period
+    *  and stuff them into the "DeletionCandidates" table.
+    */
+   edit_uint64(today - period/(3600*24), ed1);
+   Mmsg(&query, insert_delcand, ed1, cr.ClientId);
+
+   if (!db_sql_query(ua->db, query, NULL, (void *)NULL)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      Dmsg0(050, "insert delcand failed\n");
+      goto bail_out;
+   }
+
+   strcpy(query, "SELECT count(*) FROM DelCandidates");
+   
+   Dmsg1(100, "select sql=%s\n", query);
+   if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      Dmsg0(050, "Count failed\n");
+      goto bail_out;
+   }
+      
+   if (cnt.count == 0) {
+      bsendmsg(ua, _("No Jobs for client %s found to prune from %s catalog.\n"),
+        client->hdr.name, client->catalog->hdr.name);
+      goto bail_out;
+   }
+
+   if (cnt.count < MAX_DEL_LIST_LEN) {
+      del.max_ids = cnt.count + 1;
+   } else {
+      del.max_ids = MAX_DEL_LIST_LEN; 
+   }
+   del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+   del.PurgedFiles = (char *)malloc(del.max_ids);
+
+   Mmsg(&query, select_del, ed1, cr.ClientId);
+   db_sql_query(ua->db, query, job_delete_handler, (void *)&del);
+
+   /* 
+    * OK, now we have the list of JobId's to be pruned, first check
+    * if the Files have been purged, if not, purge (delete) them.
+    * Then delete the Job entry, and finally and JobMedia records.
+    */
+   for (i=0; i < del.num_ids; i++) {
+      Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+      if (!del.PurgedFiles[i]) {
+         Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+        db_sql_query(ua->db, query, NULL, (void *)NULL);
+         Dmsg1(050, "Del sql=%s\n", query);
+      }
+
+      Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      Dmsg1(050, "Del sql=%s\n", query);
+
+      Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      Dmsg1(050, "Del sql=%s\n", query);
+   }
+   bsendmsg(ua, _("%d Jobs for client %s pruned from %s catalog.\n"), del.num_ids,
+      client->hdr.name, client->catalog->hdr.name);
+   
+bail_out:
+   drop_temp_tables(ua);
+   if (del.JobId) {
+      free(del.JobId);
+   }
+   if (del.PurgedFiles) {
+      free(del.PurgedFiles);
+   }
+   free_pool_memory(query);
+   return 1;
+}
+
+/*
+ * Prune volumes
+ */
+int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
+{
+   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   struct s_count_ctx cnt;
+
+   Mmsg(&query, "SELECT count(*) FROM JobMedia WHERE MediaId=%d", mr->MediaId);
+   if (!db_sql_query(ua->db, query, count_handler, (void *)&cnt)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      Dmsg0(050, "Count failed\n");
+      goto bail_out;
+   }
+      
+   if (cnt.count == 0) {
+      bsendmsg(ua, "There are no Jobs associated with Volume %s. It is purged.\n",
+        mr->VolumeName);
+   } else {
+      bsendmsg(ua, "There are still %d Jobs on Volume %s. It is not purged.\n",
+        cnt.count, mr->VolumeName);
+   }
+bail_out:   
+   free_pool_memory(query);
+   return 1;
+}
diff --git a/bacula/src/dird/ua_purge.c b/bacula/src/dird/ua_purge.c
new file mode 100644 (file)
index 0000000..eab8d01
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ *
+ *   Bacula Director -- User Agent Database Purge Command
+ *
+ *     Purges Files from specific JobIds
+ * or
+ *     Purges Jobs from Volumes
+ *
+ *     Kern Sibbald, February MMII
+ */
+
+/*
+   Copyright (C) 2002 Kern Sibbald and John Walker
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "dird.h"
+#include "ua.h"
+
+/* Forward referenced functions */
+int purge_files_from_client(UAContext *ua, CLIENT *client);
+int purge_jobs_from_client(UAContext *ua, CLIENT *client);
+void purge_files_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr );
+void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+void purge_files_from_job(UAContext *ua, JOB_DBR *jr);
+
+
+#define MAX_DEL_LIST_LEN 1000000
+
+
+static char *select_jobsfiles_from_client =
+   "SELECT JobId FROM Job "
+   "WHERE ClientId=%d "
+   "AND PurgedFiles=0";
+
+static char *select_jobs_from_client =
+   "SELECT JobId, PurgedFiles FROM Job "
+   "WHERE ClientId=%d";
+
+
+/* In memory list of JobIds */
+struct s_file_del_ctx {
+   JobId_t *JobId;
+   int num_ids;                      /* ids stored */
+   int max_ids;                      /* size of array */
+   int num_del;                      /* number deleted */
+   int tot_ids;                      /* total to process */
+};
+
+struct s_job_del_ctx {
+   JobId_t *JobId;                   /* array of JobIds */
+   char *PurgedFiles;                /* Array of PurgedFile flags */
+   int num_ids;                      /* ids stored */
+   int max_ids;                      /* size of array */
+   int num_del;                      /* number deleted */
+   int tot_ids;                      /* total to process */
+};
+
+struct s_count_ctx {
+   int count;
+};
+
+
+/*
+ * Called here to count entries to be deleted 
+ */
+static int file_count_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+   del->tot_ids++;
+   return 0;
+}
+
+
+static int job_count_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx;
+   del->tot_ids++;
+   return 0;
+}
+
+
+/*
+ * Called here to make in memory list of JobIds to be
+ *  deleted and the associated PurgedFiles flag.
+ *  The in memory list will then be transversed
+ *  to issue the SQL DELETE commands.  Note, the list
+ *  is allowed to get to MAX_DEL_LIST_LEN to limit the
+ *  maximum malloc'ed memory.
+ */
+static int job_delete_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_job_del_ctx *del = (struct s_job_del_ctx *)ctx;
+
+   if (del->num_ids == MAX_DEL_LIST_LEN) {  
+      return 1;
+   }
+   if (del->num_ids == del->max_ids) {
+      del->max_ids = (del->max_ids * 3) / 2;
+      del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) * del->max_ids);
+      del->PurgedFiles = (char *)brealloc(del->PurgedFiles, del->max_ids);
+   }
+   del->JobId[del->num_ids] = (JobId_t)strtod(row[0], NULL);
+   del->PurgedFiles[del->num_ids++] = (char)atoi(row[0]);
+   return 0;
+}
+
+static int file_delete_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_file_del_ctx *del = (struct s_file_del_ctx *)ctx;
+
+   if (del->num_ids == MAX_DEL_LIST_LEN) {  
+      return 1;
+   }
+   if (del->num_ids == del->max_ids) {
+      del->max_ids = (del->max_ids * 3) / 2;
+      del->JobId = (JobId_t *)brealloc(del->JobId, sizeof(JobId_t) *
+        del->max_ids);
+   }
+   del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+   return 0;
+}
+
+void purge_files_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr ) {} /* ***FIXME*** implement */
+void purge_jobs_from_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr) {} /* ***FIXME*** implement */
+
+
+
+/*
+ *   Purge records from database
+ *
+ *     Purge Files from [Job|JobId|Client|Volume]
+ *     Purge Jobs  from [Client|Volume]
+ *
+ *  N.B. Not all above is implemented yet.
+ */
+int purgecmd(UAContext *ua, char *cmd)
+{
+   CLIENT *client;
+   MEDIA_DBR mr;
+   POOL_DBR pr;
+   JOB_DBR  jr;
+   static char *keywords[] = {
+      N_("files"),
+      N_("jobs"),
+      NULL};
+
+   static char *files_keywords[] = {
+      N_("Job"),
+      N_("JobId"),
+      N_("Client"),
+      N_("Volume"),
+      NULL};
+
+   static char *jobs_keywords[] = {
+      N_("Client"),
+      N_("Volume"),
+      NULL};
+      
+   bsendmsg(ua, _(
+      "This command is DANGEROUUS!\n"
+      "It purges (deletes) all Files from a Job,\n"
+      "JobId, Client or Volume; or it purges (deletes)\n"
+      "all Jobs from a Client or Volume. Normally you\n" 
+      "should use the PRUNE command instead.\n"));
+
+   if (!open_db(ua)) {
+      return 1;
+   }
+   switch (find_arg_keyword(ua, keywords)) {
+   /* Files */
+   case 0:
+      switch(find_arg_keyword(ua, files_keywords)) {
+      case 0:                        /* Job */
+      case 1:
+        if (get_job_dbr(ua, &jr)) {
+           purge_files_from_job(ua, &jr);
+        }
+        return 1;
+      case 2:                        /* client */
+        client = select_client_resource(ua);
+        purge_files_from_client(ua, client);
+        return 1;
+      case 3:
+        if (select_pool_and_media_dbr(ua, &pr, &mr)) {
+           purge_files_from_volume(ua, &pr, &mr);
+        }
+        return 1;
+      }
+   /* Jobs */
+   case 1:
+      switch(find_arg_keyword(ua, jobs_keywords)) {
+      case 0:                        /* client */
+        client = select_client_resource(ua);
+        purge_jobs_from_client(ua, client);
+        return 1;
+      case 1:
+        if (select_pool_and_media_dbr(ua, &pr, &mr)) {
+           purge_jobs_from_volume(ua, &pr, &mr);
+        }
+        return 1;
+      }
+   default:
+      break;
+   }
+   switch (do_keyword_prompt(ua, _("Choose item to purge"), keywords)) {
+   case 0:
+      client = select_client_resource(ua);
+      if (!client) {
+        return 1;
+      }
+      purge_files_from_client(ua, client);
+      break;
+   case 1:
+      client = select_client_resource(ua);
+      if (!client) {
+        return 1;
+      }
+      purge_jobs_from_client(ua, client);
+      break;
+   }
+   return 1;
+}
+
+/*
+ * Prune File records from the database. For any Job which
+ * is older than the retention period, we unconditionally delete
+ * all File records for that Job.  This is simple enough that no
+ * temporary tables are needed. We simply make an in memory list of
+ * the JobIds meeting the prune conditions, then delete all File records
+ * pointing to each of those JobIds.
+ */
+int purge_files_from_client(UAContext *ua, CLIENT *client)
+{
+   struct s_file_del_ctx del;
+   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   int i;
+   CLIENT_DBR cr;
+
+   memset(&cr, 0, sizeof(cr));
+   strcpy(cr.Name, client->hdr.name);
+   if (!db_create_client_record(ua->db, &cr)) {
+      return 0;
+   }
+
+   del.JobId = NULL;
+   del.num_ids = 0;
+   del.tot_ids = 0;
+   del.num_del = 0;
+   del.max_ids = 0;
+
+   Mmsg(&query, select_jobsfiles_from_client, cr.ClientId);
+
+   Dmsg1(050, "select sql=%s\n", query);
+   if (!db_sql_query(ua->db, query, file_count_handler, (void *)&del)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      Dmsg0(050, "Count failed\n");
+      goto bail_out;
+   }
+      
+   if (del.tot_ids == 0) {
+      bsendmsg(ua, _("No Files found for client %s to purge from %s catalog.\n"),
+        client->hdr.name, client->catalog->hdr.name);
+      goto bail_out;
+   }
+
+   if (del.tot_ids < MAX_DEL_LIST_LEN) {
+      del.max_ids = del.tot_ids + 1;
+   } else {
+      del.max_ids = MAX_DEL_LIST_LEN; 
+   }
+   del.tot_ids = 0;
+
+   del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+
+   db_sql_query(ua->db, query, file_delete_handler, (void *)&del);
+
+   for (i=0; i < del.num_ids; i++) {
+      Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+      Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      /* 
+       * Now mark Job as having files purged. This is necessary to
+       * avoid having too many Jobs to process in future prunings. If
+       * we don't do this, the number of JobId's in our in memory list
+       * will grow very large.
+       */
+      Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      Dmsg1(050, "Del sql=%s\n", query);
+   }
+   bsendmsg(ua, _("%d Files for client %s purged from %s catalog.\n"), del.num_ids,
+      client->hdr.name, client->catalog->hdr.name);
+   
+bail_out:
+   if (del.JobId) {
+      free(del.JobId);
+   }
+   free_pool_memory(query);
+   return 1;
+}
+
+
+
+/*
+ * Purging Jobs is a bit more complicated than purging Files
+ * because we delete Job records only if there is a more current
+ * backup of the FileSet. Otherwise, we keep the Job record.
+ * In other words, we never delete the only Job record that
+ * contains a current backup of a FileSet. This prevents the
+ * Volume from being recycled and destroying a current backup.
+ */
+int purge_jobs_from_client(UAContext *ua, CLIENT *client)
+{
+   struct s_job_del_ctx del;
+   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   int i;
+   CLIENT_DBR cr;
+
+   memset(&cr, 0, sizeof(cr));
+   strcpy(cr.Name, client->hdr.name);
+   if (!db_create_client_record(ua->db, &cr)) {
+      return 0;
+   }
+
+   del.JobId = NULL;
+   del.num_ids = 0;
+   del.tot_ids = 0;
+   del.num_del = 0;
+   del.max_ids = 0;
+
+   Mmsg(&query, select_jobs_from_client, cr.ClientId);
+
+   Dmsg1(050, "select sql=%s\n", query);
+   if (!db_sql_query(ua->db, query, job_count_handler, (void *)&del)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      Dmsg0(050, "Count failed\n");
+      goto bail_out;
+   }
+   if (del.tot_ids == 0) {
+      bsendmsg(ua, _("No Jobs found for client %s to purge from %s catalog.\n"),
+        client->hdr.name, client->catalog->hdr.name);
+      goto bail_out;
+   }
+
+   if (del.tot_ids < MAX_DEL_LIST_LEN) {
+      del.max_ids = del.tot_ids + 1;
+   } else {
+      del.max_ids = MAX_DEL_LIST_LEN; 
+   }
+
+   del.tot_ids = 0;
+
+      
+
+   del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
+   del.PurgedFiles = (char *)malloc(del.max_ids);
+
+   db_sql_query(ua->db, query, job_delete_handler, (void *)&del);
+
+   /* 
+    * OK, now we have the list of JobId's to be purged, first check
+    * if the Files have been purged, if not, purge (delete) them.
+    * Then delete the Job entry, and finally and JobMedia records.
+    */
+   for (i=0; i < del.num_ids; i++) {
+      Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+      if (!del.PurgedFiles[i]) {
+         Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+        db_sql_query(ua->db, query, NULL, (void *)NULL);
+         Dmsg1(050, "Del sql=%s\n", query);
+      }
+
+      Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      Dmsg1(050, "Del sql=%s\n", query);
+
+      Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]);
+      db_sql_query(ua->db, query, NULL, (void *)NULL);
+      Dmsg1(050, "Del sql=%s\n", query);
+   }
+   bsendmsg(ua, _("%d Jobs for client %s purged from %s catalog.\n"), del.num_ids,
+      client->hdr.name, client->catalog->hdr.name);
+   
+bail_out:
+   if (del.JobId) {
+      free(del.JobId);
+   }
+   if (del.PurgedFiles) {
+      free(del.PurgedFiles);
+   }
+   free_pool_memory(query);
+   return 1;
+}
+
+void purge_files_from_job(UAContext *ua, JOB_DBR *jr)
+{
+   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   
+   Mmsg(&query, "DELETE FROM File WHERE JobId=%d", jr->JobId);
+   db_sql_query(ua->db, query, NULL, (void *)NULL);
+
+   Mmsg(&query, "UPDATE Job Set PurgedFiles=1 WHERE JobId=%d", jr->JobId);
+   db_sql_query(ua->db, query, NULL, (void *)NULL);
+
+   free_pool_memory(query);
+}
index cb2693cdf61cb7d29d850062b2fb3fdd719715dd..9ad7b6b6e7d370da989d33f571e954478c57f07e 100644 (file)
@@ -208,9 +208,6 @@ CLIENT *get_client_resource(UAContext *ua)
    return select_client_resource(ua);
 }
 
-
-
-
 /* Scan what the user has entered looking for:
  * 
  *  pool=<pool-name>   
@@ -287,6 +284,47 @@ int select_pool_dbr(UAContext *ua, POOL_DBR *pr)
    return opr.PoolId;
 }
 
+/*
+ * Select a Pool and a Media (Volume) record from the database
+ */
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
+{
+   int found = FALSE;
+   int i;
+
+   memset(pr, 0, sizeof(POOL_DBR));
+   memset(mr, 0, sizeof(MEDIA_DBR));
+
+   /* Get the pool, possibly from pool=<pool-name> */
+   if (!get_pool_dbr(ua, pr)) {
+      return 0;
+   }
+   mr->PoolId = pr->PoolId;
+
+   /* See if a volume name is specified as an argument */
+   for (i=1; i<ua->argc; i++) {
+      if (strcasecmp(ua->argk[i], _("volume")) == 0 && ua->argv[i]) {
+        found = TRUE;
+        break;
+      }
+   }
+   if (found) {
+      strcpy(mr->VolumeName, ua->argv[i]);
+   } else {
+      db_list_media_records(ua->db, mr, prtit, ua);
+      if (!get_cmd(ua, _("Enter the Volume name to delete: "))) {
+        return 01;
+      }
+      strcpy(mr->VolumeName, ua->cmd);
+   }
+   mr->MediaId = 0;
+   if (!db_get_media_record(ua->db, mr)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      return 0;
+   }
+   return 1;
+}
+
 
 /*
  *  This routine is ONLY used in the create command.
@@ -321,6 +359,63 @@ POOL *get_pool_resource(UAContext *ua)
    return pool;
 }
 
+/*
+ * List all jobs and ask user to select one
+ */
+int select_job_dbr(UAContext *ua, JOB_DBR *jr)
+{
+   db_list_job_records(ua->db, jr, prtit, ua);
+   if (!get_cmd(ua, _("Enter the JobId to select: "))) {
+      return 0;
+   }
+   jr->JobId = atoi(ua->cmd);
+   if (!db_get_job_record(ua->db, jr)) {
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+      return 0;
+   }
+   return jr->JobId;
+
+}
+
+
+/* Scan what the user has entered looking for:
+ * 
+ *  jobid=nn
+ *
+ *  if error or not found, put up a list of Jobs
+ *  to choose from.
+ *
+ *   returns: 0 on error
+ *           JobId on success and fills in JOB_DBR
+ */
+int get_job_dbr(UAContext *ua, JOB_DBR *jr)
+{
+   int i;
+
+   for (i=1; i<ua->argc; i++) {
+      if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) {
+        jr->JobId = 0;
+        strcpy(jr->Job, ua->argv[i]);
+      } else if (strcasecmp(ua->argk[i], _("jobid")) == 0 && ua->argv[i]) {
+        jr->JobId = atoi(ua->argv[i]);
+      } else {
+        continue;
+      }
+      if (!db_get_job_record(ua->db, jr)) {
+         bsendmsg(ua, _("Could not find Job %s: ERR=%s"), ua->argv[i],
+                 db_strerror(ua->db));
+        jr->JobId = 0;
+        break;
+      }
+      return jr->JobId;
+   }
+
+   if (!select_job_dbr(ua, jr)) {  /* try once more */
+      return 0;
+   }
+   return jr->JobId;
+}
+
 
 
 
index a05ee54b1cb04c10d879366cffe1565aeda70147..eb8b651f71acd031e60451d0f7b8a44991b24ae6 100644 (file)
@@ -220,8 +220,8 @@ static void do_director_status(UAContext *ua, char *cmd)
       }
           
       bsendmsg(ua, _("  Files=%s Bytes=%s Termination Status=%s\n"), 
-          edit_uint_with_commas(last_job.JobFiles, b1),
-          edit_uint_with_commas(last_job.JobBytes, b2),
+          edit_uint64_with_commas(last_job.JobFiles, b1),
+          edit_uint64_with_commas(last_job.JobBytes, b2),
           termstat);
    }
    lock_jcr_chain();
index 825758a3f17bcb6a24cdbecc0f8aa7f4067c483c..b9d3a7de0f1473ad8c641c0874134f8147200edb 100644 (file)
@@ -306,7 +306,7 @@ Termination:            %s\n"),
        jcr->client->hdr.name,
        sdt,
        edt,
-       edit_uint_with_commas(jcr->jr.JobFiles, ec1),
+       edit_uint64_with_commas(jcr->jr.JobFiles, ec1),
        term_msg);
 
    Dmsg0(100, "Leave verify_cleanup()\n");
index da15c6fe650fb8f62b15eb38e41c88ec733486a0..832f7511f9c05a3a386ff3a952e5bc33c67306d1 100755 (executable)
@@ -71,8 +71,8 @@ static void do_status(void sendit(char *msg, int len, void *sarg), void *arg)
       }
           
       len = Mmsg(&msg, _("  Files=%s Bytes=%s Termination Status=%s\n"), 
-          edit_uint_with_commas(last_job.JobFiles, b1),
-          edit_uint_with_commas(last_job.JobBytes, b2),
+          edit_uint64_with_commas(last_job.JobFiles, b1),
+          edit_uint64_with_commas(last_job.JobBytes, b2),
           termstat);
       sendit(msg, len, arg);
    }
@@ -96,12 +96,12 @@ static void do_status(void sendit(char *msg, int len, void *sarg), void *arg)
       }
       bps = njcr->JobBytes / sec;
       len = Mmsg(&msg,  _("    Files=%s Bytes=%s Bytes/sec=%s\n"), 
-          edit_uint_with_commas(njcr->JobFiles, b1),
-          edit_uint_with_commas(njcr->JobBytes, b2),
-          edit_uint_with_commas(bps, b3));
+          edit_uint64_with_commas(njcr->JobFiles, b1),
+          edit_uint64_with_commas(njcr->JobBytes, b2),
+          edit_uint64_with_commas(bps, b3));
       sendit(msg, len, arg);
       len = Mmsg(&msg, _("    Files Examined=%s\n"), 
-          edit_uint_with_commas(njcr->num_files_examined, b1));
+          edit_uint64_with_commas(njcr->num_files_examined, b1));
       sendit(msg, len, arg);
       if (njcr->JobFiles > 0) {
          len = Mmsg(&msg, _("    Processing file: %s\n"), njcr->last_fname);
index 115cb327f9db222bbb8731e33833ac5c06f1fb32..2f0ec19bb07ce53dcb0f91d74d44f5a62c4a7431 100644 (file)
  */
 
 /* base64.c */
-void     base64_init            __PROTO((void));
-int      to_base64              __PROTO((intmax_t value, char *where));
-int      from_base64            __PROTO((intmax_t *value, char *where));
-void     encode_stat            __PROTO((char *buf, struct stat *statp));
-void     decode_stat            __PROTO((char *buf, struct stat *statp));
-int      bin_to_base64          __PROTO((char *buf, char *bin, int len));
+void      base64_init            __PROTO((void));
+int       to_base64              __PROTO((intmax_t value, char *where));
+int       from_base64            __PROTO((intmax_t *value, char *where));
+void      encode_stat            __PROTO((char *buf, struct stat *statp));
+void      decode_stat            __PROTO((char *buf, struct stat *statp));
+int       bin_to_base64          __PROTO((char *buf, char *bin, int len));
 
 /* bmisc.c */
-void    *b_malloc               (char *file, int line, size_t size);
+void     *b_malloc               (char *file, int line, size_t size);
 #ifndef DEBUG
-void    *bmalloc                (size_t size);
+void     *bmalloc                (size_t size);
 #endif
-void    *brealloc               (void *buf, size_t size);
-void    *bcalloc                (size_t size1, size_t size2);
-int      bsnprintf              (char *str, size_t size, const  char  *format, ...);
-int      bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
-int      pool_sprintf           (char *pool_buf, char *fmt, ...);
-int      create_pid_file        (char *dir, char *progname, int port, char *errmsg);
-int      delete_pid_file        (char *dir, char *progname, int port);
+void     *brealloc               (void *buf, size_t size);
+void     *bcalloc                (size_t size1, size_t size2);
+int       bsnprintf              (char *str, size_t size, const  char  *format, ...);
+int       bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
+int       pool_sprintf           (char *pool_buf, char *fmt, ...);
+int       create_pid_file        (char *dir, char *progname, int port, char *errmsg);
+int       delete_pid_file        (char *dir, char *progname, int port);
 
 /* bnet.c */
-int32_t    bnet_recv            __PROTO((BSOCK *bsock));
-int       bnet_send             __PROTO((BSOCK *bsock));
-int       bnet_fsend              (BSOCK *bs, char *fmt, ...);
-int       bnet_set_buffer_size    (BSOCK *bs, uint32_t size, int rw);
-int       bnet_sig                (BSOCK *bs, int sig);
-BSOCK *    bnet_connect           (void *jcr, int retry_interval,
-              int max_retry_time, char *name, char *host, char *service, 
-              int port, int verbose);
-int       bnet_wait_data         (BSOCK *bsock, int sec);
-void      bnet_close            __PROTO((BSOCK *bsock));
-BSOCK *    init_bsock           __PROTO((int sockfd, char *who, char *ip, int port));
-BSOCK *    dup_bsock            __PROTO((BSOCK *bsock));
-void      term_bsock            __PROTO((BSOCK *bsock));
-char *    bnet_strerror         __PROTO((BSOCK *bsock));
-char *    bnet_sig_to_ascii     __PROTO((BSOCK *bsock));
-int       bnet_wait_data        __PROTO((BSOCK *bsock, int sec));
+int32_t    bnet_recv             __PROTO((BSOCK *bsock));
+int        bnet_send             __PROTO((BSOCK *bsock));
+int        bnet_fsend              (BSOCK *bs, char *fmt, ...);
+int        bnet_set_buffer_size    (BSOCK *bs, uint32_t size, int rw);
+int        bnet_sig                (BSOCK *bs, int sig);
+BSOCK *    bnet_connect            (void *jcr, int retry_interval,
+               int max_retry_time, char *name, char *host, char *service, 
+               int port, int verbose);
+int        bnet_wait_data         (BSOCK *bsock, int sec);
+void       bnet_close            __PROTO((BSOCK *bsock));
+BSOCK *    init_bsock            __PROTO((int sockfd, char *who, char *ip, int port));
+BSOCK *    dup_bsock             __PROTO((BSOCK *bsock));
+void       term_bsock            __PROTO((BSOCK *bsock));
+char *     bnet_strerror         __PROTO((BSOCK *bsock));
+char *     bnet_sig_to_ascii     __PROTO((BSOCK *bsock));
+int        bnet_wait_data        __PROTO((BSOCK *bsock, int sec));
 
 
 /* cram-md5.c */
 int cram_md5_get_auth(BSOCK *bs, char *password);
 int cram_md5_auth(BSOCK *bs, char *password);
 void hmac_md5(uint8_t* text, int text_len, uint8_t*  key,
-             int key_len, uint8_t *hmac);
+              int key_len, uint8_t *hmac);
 
 /* create_file.c */
 int create_file(void *jcr, char *fname, char *ofile, char *lname,
-                      int type, struct stat *statp, int *ofd);
+                       int type, struct stat *statp, int *ofd);
 int set_statp(void *jcr, char *fname, char *ofile, char *lname, int type, 
-                      struct stat *statp);
+                       struct stat *statp);
 
 
 /* crc32.c */
 uint32_t bcrc32(uint8_t *buf, int len);
 
 /* daemon.c */
-void    daemon_start            __PROTO(());
+void     daemon_start            __PROTO(());
 
 /* lex.c */
-LEX *    lex_close_file         __PROTO((LEX *lf));
-LEX *    lex_open_file          __PROTO((LEX *lf, char *fname));
-int      lex_get_char           __PROTO((LEX *lf));
-void     lex_unget_char         __PROTO((LEX *lf));
-char *   lex_tok_to_str         __PROTO((int token));
-int      lex_get_token          __PROTO((LEX *lf));
+LEX *     lex_close_file         __PROTO((LEX *lf));
+LEX *     lex_open_file          __PROTO((LEX *lf, char *fname));
+int       lex_get_char           __PROTO((LEX *lf));
+void      lex_unget_char         __PROTO((LEX *lf));
+char *    lex_tok_to_str         __PROTO((int token));
+int       lex_get_token          __PROTO((LEX *lf));
 
 /* makepath.c */
 int make_path(
-          void *jcr,
-          const char *argpath,
-          int mode,
-          int parent_mode,
-          uid_t owner,
-          gid_t group,
-          int preserve_existing,
-          char *verbose_fmt_string);
+           void *jcr,
+           const char *argpath,
+           int mode,
+           int parent_mode,
+           uid_t owner,
+           gid_t group,
+           int preserve_existing,
+           char *verbose_fmt_string);
 
 
 /* message.c */
-void      my_name_is            __PROTO((int argc, char *argv[], char *name));
-void      init_msg              __PROTO((void *jcr));
-void      term_msg              __PROTO((void));
-void      close_msg             __PROTO((void *jcr));
-void      add_msg_dest          __PROTO((int dest, int type, char *where, char *dest_code));
-void      rem_msg_dest          __PROTO((int dest, int type, char *where));
-void      Jmsg                  (void *jcr, int type, int level, char *fmt, ...);
-void      dispatch_message      __PROTO((void *jcr, int type, int level, char *buf));
-void      init_console_msg      __PROTO((char *wd));
+void       my_name_is            __PROTO((int argc, char *argv[], char *name));
+void       init_msg              __PROTO((void *jcr));
+void       term_msg              __PROTO((void));
+void       close_msg             __PROTO((void *jcr));
+void       add_msg_dest          __PROTO((int dest, int type, char *where, char *dest_code));
+void       rem_msg_dest          __PROTO((int dest, int type, char *where));
+void       Jmsg                  (void *jcr, int type, int level, char *fmt, ...);
+void       dispatch_message      __PROTO((void *jcr, int type, int level, char *buf));
+void       init_console_msg      __PROTO((char *wd));
 
 
 /* bnet_server.c */
-void      bnet_thread_server(int port, int max_clients, workq_t *client_wq, 
-                  void handle_client_request(void *bsock));
-void            bnet_server             __PROTO((int port, void handle_client_request(BSOCK *bsock)));
-int             net_connect             __PROTO((int port));
-BSOCK *         bnet_bind               __PROTO((int port));
-BSOCK *         bnet_accept             __PROTO((BSOCK *bsock, char *who));
+void       bnet_thread_server(int port, int max_clients, workq_t *client_wq, 
+                   void handle_client_request(void *bsock));
+void             bnet_server             __PROTO((int port, void handle_client_request(BSOCK *bsock)));
+int              net_connect             __PROTO((int port));
+BSOCK *          bnet_bind               __PROTO((int port));
+BSOCK *          bnet_accept             __PROTO((BSOCK *bsock, char *who));
 
 /* signal.c */
-void            init_signals             __PROTO((void terminate(int sig)));
-void            init_stack_dump          (void);
+void             init_signals             __PROTO((void terminate(int sig)));
+void             init_stack_dump          (void);
 
 /* util.c */
-void            lcase                   __PROTO((char *str));
-void            bash_spaces             __PROTO((char *str));
-void            unbash_spaces           __PROTO((char *str));
-void            strip_trailing_junk     __PROTO((char *str));
-void            strip_trailing_slashes  __PROTO((char *dir));
-int             skip_spaces             __PROTO((char **msg));
-int             skip_nonspaces          __PROTO((char **msg));
-int             fstrsch                 __PROTO((char *a, char *b));
-char *          encode_time             __PROTO((time_t time, char *buf));
-char *          encode_mode             __PROTO((mode_t mode, char *buf));
-char *          edit_uint_with_commas   __PROTO((uint64_t val, char *buf));
-char *          add_commas              __PROTO((char *val, char *buf));
-char *          edit_uint               (uint64_t val, char *buf);
-int             do_shell_expansion      (char *name);
-int             is_a_number             (const char *num);
+void             lcase                   __PROTO((char *str));
+void             bash_spaces             __PROTO((char *str));
+void             unbash_spaces           __PROTO((char *str));
+void             strip_trailing_junk     __PROTO((char *str));
+void             strip_trailing_slashes  __PROTO((char *dir));
+int              skip_spaces             __PROTO((char **msg));
+int              skip_nonspaces          __PROTO((char **msg));
+int              fstrsch                 __PROTO((char *a, char *b));
+char *           encode_time             __PROTO((time_t time, char *buf));
+char *           encode_mode             __PROTO((mode_t mode, char *buf));
+char *           edit_uint64_with_commas   __PROTO((uint64_t val, char *buf));
+char *           add_commas              __PROTO((char *val, char *buf));
+char *           edit_uint64             (uint64_t val, char *buf);
+int              do_shell_expansion      (char *name);
+int              is_a_number             (const char *num);
 
 
 /*
- *void          print_ls_output         __PROTO((char *fname, char *lname, int type, struct stat *statp));
+ *void           print_ls_output         __PROTO((char *fname, char *lname, int type, struct stat *statp));
  */
 
 /* watchdog.c */
index 99b0d42dbbee8cf566da205a41a2fd3e8acfa7ed..aaa7d72679565902756808e9beba2bf05ffe85ab 100644 (file)
@@ -65,7 +65,7 @@ int is_a_number(const char *n)
  * must be at least 27 bytes long.  The incoming number
  * is always widened to 64 bits.
  */
-char *edit_uint_with_commas(uint64_t val, char *buf)
+char *edit_uint64_with_commas(uint64_t val, char *buf)
 {
    sprintf(buf, "%" lld, val);
    return add_commas(buf, buf);
@@ -76,7 +76,7 @@ char *edit_uint_with_commas(uint64_t val, char *buf)
  * must be at least 27 bytes long.  The incoming number
  * is always widened to 64 bits.
  */
-char *edit_uint(uint64_t val, char *buf)
+char *edit_uint64(uint64_t val, char *buf)
 {
    sprintf(buf, "%" lld, val);
    return buf;
index c577e6dfab20731428e66406d809c684889ba8c4..629fff8515e706aa2a4260fa9128bc89e895c477 100644 (file)
@@ -569,8 +569,8 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 
       /* Inform User about end of media */
       Jmsg(jcr, M_INFO, 0, _("End of media on Volume %s Bytes=%s Blocks=%s.\n"), 
-          PrevVolName, edit_uint_with_commas(dev->VolCatInfo.VolCatBytes, b1),
-          edit_uint_with_commas(dev->VolCatInfo.VolCatBlocks, b2));
+          PrevVolName, edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
+          edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2));
 
       if (!dev_is_tape(dev)) {          /* If file, */
         close_dev(dev);                 /* yes, close it */
index 7713d9626f5a7e483bc6ae208caa2c305d1e2933..4b81b143695e9fd90227f71360f5857a81937f73 100644 (file)
@@ -620,8 +620,8 @@ static int status_cmd(JCR *jcr)
       }
           
       bnet_fsend(user, _("  Files=%s Bytes=%s Termination Status=%s\n"), 
-          edit_uint_with_commas(last_job.JobFiles, b1),
-          edit_uint_with_commas(last_job.JobBytes, b2),
+          edit_uint64_with_commas(last_job.JobFiles, b1),
+          edit_uint64_with_commas(last_job.JobBytes, b2),
           termstat);
    }
 
@@ -665,12 +665,12 @@ static int status_cmd(JCR *jcr)
            }
            bpb = dev->VolCatInfo.VolCatBytes / bpb;
             bnet_fsend(user, _("    Total Bytes=%s Blocks=%s Bytes/block=%s\n"),
-              edit_uint_with_commas(dev->VolCatInfo.VolCatBytes, b1),
-              edit_uint_with_commas(dev->VolCatInfo.VolCatBlocks, b2), 
-              edit_uint_with_commas(bpb, b3));
+              edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, b1),
+              edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), 
+              edit_uint64_with_commas(bpb, b3));
             bnet_fsend(user, _("    Positioned at File=%s Block=%s\n"), 
-              edit_uint_with_commas(dev->file, b1),
-              edit_uint_with_commas(dev->block_num, b2));
+              edit_uint64_with_commas(dev->file, b1),
+              edit_uint64_with_commas(dev->block_num, b2));
 
         } else {
             bnet_fsend(user, _("Device %s is not open.\n"), dev_name(dev));
@@ -696,9 +696,9 @@ static int status_cmd(JCR *jcr)
         }
         bps = jcr->JobBytes / sec;
          bnet_fsend(user, _("    Files=%s Bytes=%s Bytes/sec=%s\n"), 
-           edit_uint_with_commas(jcr->JobFiles, b1),
-           edit_uint_with_commas(jcr->JobBytes, b2),
-           edit_uint_with_commas(bps, b3));
+           edit_uint64_with_commas(jcr->JobFiles, b1),
+           edit_uint64_with_commas(jcr->JobBytes, b2),
+           edit_uint64_with_commas(bps, b3));
         found = 1;
 #ifdef DEBUG
         if (jcr->file_bsock) {
index 45e22a90202af56b903e32cb2914c157a78134d6..8287cdffe2f4c79388136c65cc0ebe9562e613ec 100644 (file)
@@ -597,13 +597,13 @@ StartFile         : %s\n\
 EndFile           : %s\n\
 JobErrors         : %s\n\
 ",
-        edit_uint_with_commas(label.JobFiles, ec1),
-        edit_uint_with_commas(label.JobBytes, ec2),
-        edit_uint_with_commas(label.start_block, ec3),
-        edit_uint_with_commas(label.end_block, ec4),
-        edit_uint_with_commas(label.start_file, ec5),
-        edit_uint_with_commas(label.end_file, ec6),
-        edit_uint_with_commas(label.JobErrors, ec7));
+        edit_uint64_with_commas(label.JobFiles, ec1),
+        edit_uint64_with_commas(label.JobBytes, ec2),
+        edit_uint64_with_commas(label.start_block, ec3),
+        edit_uint64_with_commas(label.end_block, ec4),
+        edit_uint64_with_commas(label.start_file, ec5),
+        edit_uint64_with_commas(label.end_file, ec6),
+        edit_uint64_with_commas(label.JobErrors, ec7));
    }
    dt.julian_day_number   = label.write_date;
    dt.julian_day_fraction = label.write_time;