]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/cats/bvfs.c
Add %D option to edit_job_code, simplify callbacks on director side
[bacula/bacula] / bacula / src / cats / bvfs.c
index 9dd5dd06f573e1fcf194140444b4fcba18e53357..9131a00baf5c79a8bb1112c7070d49bb9e767d4d 100644 (file)
    Switzerland, email:ftf@fsfeurope.org.
 */
 
-#define __SQL_C                       /* indicate that this is sql.c */
-
 #include "bacula.h"
-#include "cats/cats.h"
+
+#if HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
+
+#include "cats.h"
+#include "bdb_priv.h"
+#include "sql_glue.h"
 #include "lib/htable.h"
 #include "bvfs.h"
 
@@ -196,6 +199,15 @@ char *bvfs_parent_dir(char *path)
    char *p = path;
    int len = strlen(path) - 1;
 
+   /* windows directory / */
+   if (len == 2 && B_ISALPHA(path[0]) 
+                && path[1] == ':' 
+                && path[2] == '/')
+   {
+      len = 0;
+      path[0] = '\0';
+   }
+
    if (len >= 0 && path[len] == '/') {      /* if directory, skip last / */
       path[len] = '\0';
    }
@@ -375,7 +387,17 @@ static void update_path_hierarchy_cache(JCR *jcr,
       free(result);
    }
 
-   Mmsg(mdb->cmd, 
+   if (mdb->db_get_type_index() == SQL_TYPE_SQLITE3) {
+      Mmsg(mdb->cmd, 
+ "INSERT INTO PathVisibility (PathId, JobId) "
+   "SELECT DISTINCT h.PPathId AS PathId, %s "
+     "FROM PathHierarchy AS h "
+    "WHERE h.PathId IN (SELECT PathId FROM PathVisibility WHERE JobId=%s) "
+      "AND h.PPathId NOT IN (SELECT PathId FROM PathVisibility WHERE JobId=%s)",
+           jobid, jobid, jobid );
+
+   } else {
+      Mmsg(mdb->cmd, 
   "INSERT INTO PathVisibility (PathId, JobId)  "
    "SELECT a.PathId,%s "
    "FROM ( "
@@ -387,6 +409,7 @@ static void update_path_hierarchy_cache(JCR *jcr,
           "FROM PathVisibility "
          "WHERE JobId=%s) AS b ON (a.PathId = b.PathId) "
    "WHERE b.PathId IS NULL",  jobid, jobid, jobid);
+   }
 
    do {
       QUERY_DB(jcr, mdb, mdb->cmd);
@@ -422,7 +445,6 @@ void bvfs_update_cache(JCR *jcr, B_DB *mdb)
    db_list_ctx jobids_list;
 
    db_lock(mdb);
-   db_start_transaction(jcr, mdb);
 
 #ifdef xxx
    /* TODO: Remove this code when updating make_bacula_table script */
@@ -473,7 +495,6 @@ void bvfs_update_cache(JCR *jcr, B_DB *mdb)
 
    bvfs_update_path_hierarchy_cache(jcr, mdb, jobids_list.list);
 
-   db_end_transaction(jcr, mdb);
    db_start_transaction(jcr, mdb);
    Dmsg0(dbglevel, "Cleaning pathvisibility\n");
    Mmsg(mdb->cmd, 
@@ -611,11 +632,11 @@ void Bvfs::ls_special_dirs()
 
    POOL_MEM query;
    Mmsg(query, 
-"((SELECT PPathId AS PathId, '..' AS Path "
+"(SELECT PPathId AS PathId, '..' AS Path "
     "FROM  PathHierarchy "
-   "WHERE  PathId = %s) "
+   "WHERE  PathId = %s "
 "UNION "
- "(SELECT %s AS PathId, '.' AS Path))",
+ "SELECT %s AS PathId, '.' AS Path)",
         edit_uint64(pwd_id, ed1), ed1);
 
    POOL_MEM query2;
@@ -643,9 +664,11 @@ bool Bvfs::ls_dirs()
       return false;
    }
 
+   POOL_MEM query;
    POOL_MEM filter;
    if (*pattern) {
-      Mmsg(filter, " AND Path2.Path %s '%s' ", SQL_MATCH, pattern);
+      Mmsg(filter, " AND Path2.Path %s '%s' ", 
+           match_query[db_get_type_index(db)], pattern);
    }
 
    if (!dir_filenameid) {
@@ -661,7 +684,6 @@ bool Bvfs::ls_dirs()
     * my $dir_filenameid = $self->get_dir_filenameid();
     */
    /* Then we get all the dir entries from File ... */
-   POOL_MEM query;
    Mmsg(query,
 //       0     1     2   3      4     5       6
 "SELECT 'D', PathId, 0, Path, JobId, LStat, FileId FROM ( "
@@ -677,7 +699,7 @@ bool Bvfs::ls_dirs()
       "JOIN PathVisibility AS PathVisibility1 "
         "ON (PathHierarchy1.PathId = PathVisibility1.PathId) "
       "WHERE PathHierarchy1.PPathId = %s "
-      "AND PathVisibility1.jobid IN (%s) "
+      "AND PathVisibility1.JobId IN (%s) "
            "%s "
      ") AS listpath1 "
    "JOIN Path AS Path1 ON (listpath1.PathId = Path1.PathId) "
@@ -700,7 +722,7 @@ bool Bvfs::ls_dirs()
 
    db_lock(db);
    db_sql_query(db, query.c_str(), path_handler, this);
-   nb_record = db->num_rows;
+   nb_record = sql_num_rows(db);
    db_unlock(db);
 
    return nb_record == limit;
@@ -710,12 +732,12 @@ void build_ls_files_query(B_DB *db, POOL_MEM &query,
                           const char *JobId, const char *PathId,  
                           const char *filter, int64_t limit, int64_t offset)
 {
-   if (db_type == SQL_TYPE_POSTGRESQL) {
-      Mmsg(query, sql_bvfs_list_files[db_type], 
+   if (db_get_type_index(db) == SQL_TYPE_POSTGRESQL) {
+      Mmsg(query, sql_bvfs_list_files[db_get_type_index(db)], 
            JobId, PathId, JobId, PathId, 
            filter, limit, offset);
    } else {
-      Mmsg(query, sql_bvfs_list_files[db_type], 
+      Mmsg(query, sql_bvfs_list_files[db_get_type_index(db)], 
            JobId, PathId, JobId, PathId, 
            limit, offset, filter, JobId, JobId);
    }
@@ -739,7 +761,8 @@ bool Bvfs::ls_files()
 
    edit_uint64(pwd_id, pathid);
    if (*pattern) {
-      Mmsg(filter, " AND Filename.Name %s '%s' ", SQL_MATCH, pattern);
+      Mmsg(filter, " AND Filename.Name %s '%s' ", 
+           match_query[db_get_type_index(db)], pattern);
    }
 
    build_ls_files_query(db, query, 
@@ -750,7 +773,7 @@ bool Bvfs::ls_files()
 
    db_lock(db);
    db_sql_query(db, query.c_str(), list_entries, user_data);
-   nb_record = db->num_rows;
+   nb_record = sql_num_rows(db);
    db_unlock(db);
 
    return nb_record == limit;
@@ -811,6 +834,15 @@ static bool check_temp(char *output_table)
    return false;
 }
 
+void Bvfs::clear_cache()
+{
+   db_sql_query(db, "BEGIN",                     NULL, NULL);
+   db_sql_query(db, "UPDATE Job SET HasCache=0", NULL, NULL);
+   db_sql_query(db, "TRUNCATE PathHierarchy",    NULL, NULL);
+   db_sql_query(db, "TRUNCATE PathVisibility",   NULL, NULL);
+   db_sql_query(db, "COMMIT",                    NULL, NULL);
+}
+
 bool Bvfs::drop_restore_list(char *output_table)
 {
    POOL_MEM query;
@@ -842,16 +874,17 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
       return false;
    }
 
-   Mmsg(query, "CREATE TEMPORARY TABLE btemp%s AS ", output_table);
+   Mmsg(query, "CREATE TABLE btemp%s AS ", output_table);
 
-   if (*fileid) {
+   if (*fileid) {               /* Select files with their direct id */
       init=true;
-      Mmsg(tmp,"(SELECT JobId, JobTDate, FileIndex, FilenameId, PathId, FileId "
-                  "FROM File JOIN Job USING (JobId) WHERE FileId IN (%s))",
+      Mmsg(tmp,"SELECT JobId, JobTDate, FileIndex, FilenameId, PathId, FileId "
+                  "FROM File JOIN Job USING (JobId) WHERE FileId IN (%s)",
            fileid);
       pm_strcat(query, tmp.c_str());
    }
 
+   /* Add a directory content */
    while (get_next_id_from_list(&dirid, &id) == 1) {
       Mmsg(tmp, "SELECT Path FROM Path WHERE PathId=%lld", id);
       
@@ -886,14 +919,27 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
       if (init) {
          query.strcat(" UNION ");
       }
-      /* TODO: Add basejobs here */
-      Mmsg(tmp, "(SELECT JobId, JobTDate, File.FileIndex, File.FilenameId, "
+
+      Mmsg(tmp, "SELECT JobId, JobTDate, File.FileIndex, File.FilenameId, "
                         "File.PathId, FileId "
                    "FROM Path JOIN File USING (PathId) JOIN Job USING (JobId) "
-                  "WHERE Path.Path LIKE '%s' AND File.JobId IN (%s)) ", 
+                  "WHERE Path.Path LIKE '%s' AND File.JobId IN (%s) ", 
            tmp2.c_str(), jobids); 
       query.strcat(tmp.c_str());
       init = true;
+
+      query.strcat(" UNION ");
+
+      /* A directory can have files from a BaseJob */
+      Mmsg(tmp, "SELECT File.JobId, JobTDate, BaseFiles.FileIndex, "
+                        "File.FilenameId, File.PathId, BaseFiles.FileId "
+                   "FROM BaseFiles "
+                        "JOIN File USING (FileId) "
+                        "JOIN Job ON (BaseFiles.JobId = Job.JobId) "
+                        "JOIN Path USING (PathId) "
+                  "WHERE Path.Path LIKE '%s' AND BaseFiles.JobId IN (%s) ", 
+           tmp2.c_str(), jobids); 
+      query.strcat(tmp.c_str());
    }
 
    /* expect jobid,fileindex */
@@ -909,11 +955,11 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
                query.strcat(" UNION ");
             }
          } else {               /* end last job, start new one */
-            tmp.strcat(")) UNION ");
+            tmp.strcat(") UNION ");
             query.strcat(tmp.c_str());
          }
-         Mmsg(tmp, "(SELECT JobId, JobTDate, FileIndex, FilenameId, "
-                           "PathId, FileId "
+         Mmsg(tmp,   "SELECT JobId, JobTDate, FileIndex, FilenameId, "
+                            "PathId, FileId "
                        "FROM File JOIN Job USING (JobId) WHERE JobId = %lld " 
                         "AND FileIndex IN (%lld", jobid, id);
          prev_jobid = jobid;
@@ -925,7 +971,7 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
    }
 
    if (prev_jobid != 0) {       /* end last job */
-      tmp.strcat(")) ");
+      tmp.strcat(") ");
       query.strcat(tmp.c_str());
       init = true;
    }
@@ -938,7 +984,7 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
    }
 
    /* TODO: handle basejob and SQLite3 */
-   Mmsg(query, sql_bvfs_select[db_type], output_table, output_table);
+   Mmsg(query, sql_bvfs_select[db_get_type_index(db)], output_table, output_table);
 
    /* TODO: handle jobid filter */
    Dmsg1(dbglevel_sql, "q=%s\n", query.c_str());
@@ -948,9 +994,14 @@ bool Bvfs::compute_restore_list(char *fileid, char *dirid, char *hardlink,
    }
 
    /* MySQL need it */
-   if (db_type == SQL_TYPE_MYSQL) {
+   if (db_get_type_index(db) == SQL_TYPE_MYSQL) {
       Mmsg(query, "CREATE INDEX idx_%s ON b2%s (JobId)", 
            output_table, output_table);
+      Dmsg1(dbglevel_sql, "q=%s\n", query.c_str());
+      if (!db_sql_query(db, query.c_str(), NULL, NULL)) {
+         Dmsg0(dbglevel, "Can't execute q\n");
+         goto bail_out;
+      }
    }
 
    ret = true;
@@ -960,3 +1011,5 @@ bail_out:
    db_sql_query(db, query.c_str(), NULL, NULL);
    return ret;
 }
+
+#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI */