]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/cats/sql_delete.c
kes Fix memory leak with storage ids in cats/sql_get.c
[bacula/bacula] / bacula / src / cats / sql_delete.c
index 74076eb651033f17950558fcfbea1c132d62d651..f2df973ac74e49bb93c1cc940a2c1fa29977de03 100644 (file)
@@ -1,43 +1,50 @@
 /*
  * Bacula Catalog Database Delete record interface routines
- * 
+ *
  *    Kern Sibbald, December 2000
  *
  *    Version $Id$
  */
-
 /*
-   Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
+   Bacula® - The Network Backup Solution
 
-   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.
+   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
 
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public
-   License along with this program; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
- */
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 
 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
 
 /* The following is necessary so that we do not include
  * the dummy external definition of DB.
  */
-#define __SQL_C                      /* indicate that this is sql.c */
+#define __SQL_C                       /* indicate that this is sql.c */
 
 #include "bacula.h"
 #include "cats.h"
 
 
-#if    HAVE_MYSQL || HAVE_SQLITE
+#if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
 /* -----------------------------------------------------------------------
  *
  *   Generic Routines (or almost generic)
  * -----------------------------------------------------------------------
  */
 
-/* Imported subroutines */
-extern void print_dashes(B_DB *mdb);
-extern void print_result(B_DB *mdb);
-extern int QueryDB(char *file, int line, B_DB *db, char *select_cmd);
-extern int DeleteDB(char *file, int line, B_DB *db, char *delete_cmd);
-       
 /*
  * Delete Pool record, must also delete all associated
  *  Media records.
  *
  *  Returns: 0 on error
- *          1 on success
- *          PoolId = number of Pools deleted (should be 1)
- *          NumVols = number of Media records deleted
+ *           1 on success
+ *           PoolId = number of Pools deleted (should be 1)
+ *           NumVols = number of Media records deleted
  */
 int
-db_delete_pool_record(B_DB *mdb, POOL_DBR *pr)
+db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
 {
    SQL_ROW row;
 
    db_lock(mdb);
-   Mmsg(&mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", pr->Name);
+   Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", pr->Name);
    Dmsg1(10, "selectpool: %s\n", mdb->cmd);
 
    pr->PoolId = pr->NumVols = 0;
 
-   if (QUERY_DB(mdb, mdb->cmd)) {
+   if (QUERY_DB(jcr, mdb, mdb->cmd)) {
 
       mdb->num_rows = sql_num_rows(mdb);
-   
+
       if (mdb->num_rows == 0) {
-         Mmsg(&mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
-        sql_free_result(mdb);
-        db_unlock(mdb);
-        return 0;
+         Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
+         sql_free_result(mdb);
+         db_unlock(mdb);
+         return 0;
       } else if (mdb->num_rows != 1) {
-         Mmsg(&mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows);
-        sql_free_result(mdb);
-        db_unlock(mdb);
-        return 0;
+         Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), mdb->num_rows);
+         sql_free_result(mdb);
+         db_unlock(mdb);
+         return 0;
       }
       if ((row = sql_fetch_row(mdb)) == NULL) {
          Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
-        db_unlock(mdb);
-        return 0;
+         db_unlock(mdb);
+         return 0;
       }
-      pr->PoolId = atoi(row[0]);
+      pr->PoolId = str_to_int64(row[0]);
       sql_free_result(mdb);
    }
 
    /* Delete Media owned by this pool */
-   Mmsg(&mdb->cmd,
+   Mmsg(mdb->cmd,
 "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId);
 
-   pr->NumVols = DELETE_DB(mdb, mdb->cmd);
+   pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd);
    Dmsg1(200, "Deleted %d Media records\n", pr->NumVols);
 
    /* Delete Pool */
-   Mmsg(&mdb->cmd,
+   Mmsg(mdb->cmd,
 "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId);
-   pr->PoolId = DELETE_DB(mdb, mdb->cmd);
+   pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd);
    Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
 
    db_unlock(mdb);
@@ -115,11 +116,11 @@ db_delete_pool_record(B_DB *mdb, POOL_DBR *pr)
 #define MAX_DEL_LIST_LEN 1000000
 
 struct s_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 */
+   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 */
 };
 
 /*
@@ -133,35 +134,36 @@ static int delete_handler(void *ctx, int num_fields, char **row)
 {
    struct s_del_ctx *del = (struct s_del_ctx *)ctx;
 
-   if (del->num_ids == MAX_DEL_LIST_LEN) {  
+   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->max_ids);
    }
-   del->JobId[del->num_ids++] = (JobId_t)strtod(row[0], NULL);
+   del->JobId[del->num_ids++] = (JobId_t)str_to_int64(row[0]);
    return 0;
 }
 
 
-/* 
- * This routine will purge (delete) all records 
+/*
+ * This routine will purge (delete) all records
  * associated with a particular Volume. It will
  * not delete the media record itself.
  */
 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
 {
-   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
    struct s_del_ctx del;
+   char ed1[50];
    int i;
 
    del.num_ids = 0;
    del.tot_ids = 0;
    del.num_del = 0;
    del.max_ids = 0;
-   Mmsg(&mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
+   Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId);
    del.max_ids = mr->VolJobs;
    if (del.max_ids < 100) {
       del.max_ids = 100;
@@ -173,11 +175,11 @@ static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
 
    for (i=0; i < del.num_ids; i++) {
       Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]);
-      Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]);
+      Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
       db_sql_query(mdb, query, NULL, (void *)NULL);
-      Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
+      Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
       db_sql_query(mdb, query, NULL, (void *)NULL);
-      Mmsg(&query, "DELETE FROM JobMedia WHERE JobId=%d", del.JobId[i]);
+      Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1));
       db_sql_query(mdb, query, NULL, (void *)NULL);
    }
    free(del.JobId);
@@ -188,41 +190,51 @@ static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
 /* Delete Media record and all records that
  * are associated with it.
  */
-int db_delete_media_record(B_DB *mdb, MEDIA_DBR *mr)
+int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
 {
-   if (mr->MediaId == 0 && !db_get_media_record(mdb, mr)) {
+   db_lock(mdb);
+   if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
+      db_unlock(mdb);
       return 0;
-   } 
-   /* Delete associated records */
-   do_media_purge(mdb, mr);
+   }
+   /* Do purge if not already purged */
+   if (strcmp(mr->VolStatus, "Purged") != 0) {
+      /* Delete associated records */
+      do_media_purge(mdb, mr);
+   }
 
-   Mmsg(&mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
+   Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId);
    db_sql_query(mdb, mdb->cmd, NULL, (void *)NULL);
+   db_unlock(mdb);
    return 1;
 }
 
 /*
- * Purge all records associated with a 
+ * Purge all records associated with a
  * media record. This does not delete the
  * media record itself. But the media status
  * is changed to "Purged".
  */
-int db_purge_media_record(B_DB *mdb, MEDIA_DBR *mr)
+int db_purge_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
 {
-   if (mr->MediaId == 0 && !db_get_media_record(mdb, mr)) {
+   db_lock(mdb);
+   if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) {
+      db_unlock(mdb);
       return 0;
-   } 
+   }
    /* Delete associated records */
-   do_media_purge(mdb, mr);
+   do_media_purge(mdb, mr);           /* Note, always purge */
 
    /* Mark Volume as purged */
    strcpy(mr->VolStatus, "Purged");
-   if (!db_update_media_record(mdb, mr)) {
+   if (!db_update_media_record(jcr, mdb, mr)) {
+      db_unlock(mdb);
       return 0;
    }
 
+   db_unlock(mdb);
    return 1;
 }
 
 
-#endif /* HAVE_MYSQL || HAVE_SQLITE */
+#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/