]> git.sur5r.net Git - bacula/bacula/commitdiff
Implement Auto Prune and Auto Recycle
authorKern Sibbald <kern@sibbald.com>
Tue, 21 May 2002 16:21:25 +0000 (16:21 +0000)
committerKern Sibbald <kern@sibbald.com>
Tue, 21 May 2002 16:21:25 +0000 (16:21 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@26 91ce42f0-d328-0410-95d8-f526ca767f89

40 files changed:
bacula/src/bc_types.h
bacula/src/cats/bdb.c
bacula/src/cats/bdb_create.c
bacula/src/cats/bdb_delete.c
bacula/src/cats/bdb_find.c
bacula/src/cats/bdb_get.c
bacula/src/cats/bdb_list.c
bacula/src/cats/bdb_update.c
bacula/src/cats/cats.h
bacula/src/cats/mysql.c
bacula/src/cats/protos.h
bacula/src/cats/sql.c
bacula/src/cats/sql_create.c
bacula/src/cats/sql_delete.c
bacula/src/cats/sql_find.c
bacula/src/cats/sql_get.c
bacula/src/cats/sql_list.c
bacula/src/cats/sql_update.c
bacula/src/cats/sqlite.c
bacula/src/dird/Makefile.in
bacula/src/dird/autoprune.c [new file with mode: 0644]
bacula/src/dird/backup.c
bacula/src/dird/catreq.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/protos.h
bacula/src/dird/ua_prune.c
bacula/src/dird/verify.c
bacula/src/jcr.h
bacula/src/lib/Makefile.in
bacula/src/lib/bnet.c
bacula/src/lib/jcr.c
bacula/src/lib/lib.h
bacula/src/lib/message.c
bacula/src/lib/message.h
bacula/src/lib/parse_conf.c
bacula/src/lib/rwlock.c
bacula/src/lib/rwlock.h
bacula/src/stored/device.c
bacula/src/version.h

index 56922205fbcd00e091d9b5660f13f277921f1a09..4de25ce837cbd6aed59356736c68c206f0677c53 100644 (file)
@@ -42,7 +42,7 @@
 /* ****FIXME***** implement 64 bit file addresses ! */
 #define faddr_t long 
 
-#define POOLMEM char
+typedef char POOLMEM;
 
 /* Types */
 
index 063f59fa7165b322884429a7e866ac8ef871bb3b..7e3a3da6cc141ec779ab71f4128c36191f5250ae 100644 (file)
@@ -68,11 +68,12 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 #define DB_CLIENT_FILENAME   "client.db"
 #define DB_FILESET_FILENAME  "fileset.db"
 
-static char *make_filename(B_DB *mdb, char *name)
+static POOLMEM *make_filename(B_DB *mdb, char *name)
 {
-   char *dbf, sep;
+   char sep;
+   POOLMEM *dbf;
 
-   dbf = (char *) get_pool_memory(PM_FNAME);
+   dbf = get_pool_memory(PM_FNAME);
    if (working_directory[strlen(working_directory)-1] == '/') {
       sep = 0;
    } else {
@@ -117,9 +118,9 @@ db_init_database(char *db_name, char *db_user, char *db_password)
    memset(mdb, 0, sizeof(B_DB));
    Dmsg0(200, "DB struct init\n");
    mdb->db_name = bstrdup(db_name);
-   mdb->errmsg = (char *) get_pool_memory(PM_EMSG);
+   mdb->errmsg = get_pool_memory(PM_EMSG);
    *mdb->errmsg = 0;
-   mdb->cmd = (char *) get_pool_memory(PM_EMSG);  /* command buffer */
+   mdb->cmd = get_pool_memory(PM_EMSG);  /* command buffer */
    mdb->ref_count = 1;
    qinsert(&db_list, &mdb->bq);       /* put db in list */
    Dmsg0(200, "Done db_open_database()\n");
@@ -143,13 +144,21 @@ db_open_database(B_DB *mdb)
    Dmsg1(200, "db_open_database() %s\n", mdb->db_name);
 
    P(mutex);
+#ifdef needed
    if ((errstat = pthread_mutex_init(&(mdb->mutex), NULL)) != 0) {
       Mmsg1(&mdb->errmsg, "Unable to initialize DB mutex. ERR=%s\n", strerror(errstat));
       V(mutex);
       return 0;
    }
-   P(mdb->mutex);                    /* test it once */
-   V(mdb->mutex);
+   db_lock(mdb);                    /* test it once */
+   db_unlock(mdb);
+#endif
+
+   if (rwl_init(&mdb->lock) != 0) {
+      Mmsg1(&mdb->errmsg, "Unable to initialize DB lock. ERR=%s\n", strerror(errno));
+      V(mutex);
+      return 0;
+   }
 
    Dmsg0(200, "make_filename\n");
    dbf = make_filename(mdb, DB_CONTROL_FILENAME);
@@ -257,7 +266,8 @@ void db_close_database(B_DB *mdb)
       if (mdb->filesetfd) {
         fclose(mdb->filesetfd);
       }
-      pthread_mutex_destroy(&mdb->mutex);
+/*    pthread_mutex_destroy(&mdb->mutex); */
+      rwl_destroy(&mdb->lock);      
       free_pool_memory(mdb->errmsg);
       free_pool_memory(mdb->cmd);
       free(mdb);
@@ -416,4 +426,23 @@ int bdb_open_media_file(B_DB *mdb)
    return 1;
 }
 
+
+void _db_lock(char *file, int line, B_DB *mdb)
+{
+   int errstat;
+   if ((errstat=rwl_writelock(&mdb->lock)) != 0) {
+      e_msg(file, line, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
+          strerror(errstat));
+   }
+}    
+
+void _db_unlock(char *file, int line, B_DB *mdb)
+{
+   int errstat;
+   if ((errstat=rwl_writeunlock(&mdb->lock)) != 0) {
+      e_msg(file, line, M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
+          strerror(errstat));
+   }
+}    
+
 #endif /* HAVE_BACULA_DB */
index 8d6ecccb827f512ff85bbafd0197e7b54bac5c67..713e2486dd71ae199343350e25916559ef95e09a 100644 (file)
@@ -80,9 +80,9 @@ int db_create_job_record(B_DB *mdb, JOB_DBR *jr)
 {
    int len;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_jobs_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    mdb->control.JobId++;
@@ -93,11 +93,11 @@ int db_create_job_record(B_DB *mdb, JOB_DBR *jr)
    fseek(mdb->jobfd, 0L, SEEK_END);
    if (fwrite(jr, len, 1, mdb->jobfd) != 1) {
       Mmsg1(&mdb->errmsg, "Error writing DB Jobs file. ERR=%s\n", strerror(errno));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fflush(mdb->jobfd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -109,9 +109,9 @@ int db_create_jobmedia_record(B_DB *mdb, JOBMEDIA_DBR *jm)
 {
    int len;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_jobmedia_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    mdb->control.JobMediaId++;
@@ -123,11 +123,11 @@ int db_create_jobmedia_record(B_DB *mdb, JOBMEDIA_DBR *jm)
    fseek(mdb->jobmediafd, 0L, SEEK_END);
    if (fwrite(jm, len, 1, mdb->jobmediafd) != 1) {
       Mmsg1(&mdb->errmsg, "Error writing DB JobMedia file. ERR=%s\n", strerror(errno));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fflush(mdb->jobmediafd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return jm->JobMediaId;
 }
 
@@ -149,9 +149,9 @@ int db_create_pool_record(B_DB *mdb, POOL_DBR *pr)
       return 0;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_pools_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
 
@@ -163,11 +163,11 @@ int db_create_pool_record(B_DB *mdb, POOL_DBR *pr)
    fseek(mdb->poolfd, 0L, SEEK_END);
    if (fwrite(pr, len, 1, mdb->poolfd) != 1) {
       Mmsg1(&mdb->errmsg, "Error writing DB Pools file. ERR=%s\n", strerror(errno));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fflush(mdb->poolfd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -192,7 +192,7 @@ int db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
       return 0;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
 
    mdb->control.MediaId++;
    mr->MediaId = mdb->control.MediaId;
@@ -202,11 +202,11 @@ int db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
    fseek(mdb->mediafd, 0L, SEEK_END);
    if (fwrite(mr, len, 1, mdb->mediafd) != 1) {
       Mmsg1(&mdb->errmsg, "Error writing DB Media file. ERR=%s\n", strerror(errno));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fflush(mdb->mediafd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -227,9 +227,9 @@ int db_create_client_record(B_DB *mdb, CLIENT_DBR *cr)
       return 1;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_client_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
 
@@ -241,11 +241,11 @@ int db_create_client_record(B_DB *mdb, CLIENT_DBR *cr)
    len = sizeof(lcr);
    if (fwrite(cr, len, 1, mdb->clientfd) != 1) {
       Mmsg1(&mdb->errmsg, "Error writing DB Client file. ERR=%s\n", strerror(errno));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fflush(mdb->clientfd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -268,9 +268,9 @@ int db_create_fileset_record(B_DB *mdb, FILESET_DBR *fsr)
       return 1;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_fileset_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
 
@@ -282,11 +282,11 @@ int db_create_fileset_record(B_DB *mdb, FILESET_DBR *fsr)
    len = sizeof(lfsr);
    if (fwrite(fsr,  len, 1, mdb->filesetfd) != 1) {
       Mmsg1(&mdb->errmsg, "Error writing DB FileSet file. ERR=%s\n", strerror(errno));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fflush(mdb->filesetfd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
index 5ccbd071c3112cd51bcbddae8454a14de6d21a1a..ec5d53a3173813f804e29c9339c9717608fc927a 100644 (file)
@@ -71,11 +71,11 @@ int db_delete_pool_record(B_DB *mdb, POOL_DBR *pr)
       Mmsg1(&mdb->errmsg, "No pool record %s exists\n", pr->Name);
       return 0;
    }
-   P(mdb->mutex);
+   db_lock(mdb);
    fseek(mdb->poolfd, pr->rec_addr, SEEK_SET);
    memset(&opr, 0, sizeof(opr));
    stat = fwrite(&opr, sizeof(opr), 1, mdb->poolfd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat; 
 }
 
@@ -88,11 +88,11 @@ int db_delete_media_record(B_DB *mdb, MEDIA_DBR *mr)
       Mmsg0(&mdb->errmsg, "Media record not found.\n");
       return 0;
    }
-   P(mdb->mutex);
+   db_lock(mdb);
    fseek(mdb->mediafd, mr->rec_addr, SEEK_SET);
    memset(&omr, 0, sizeof(omr));
    stat = fwrite(&omr, sizeof(omr), 1, mdb->mediafd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat; 
 }
 
index 9e99479b16c703e8f4df3045e61dcfc98831c08a..eee4ea7b188de2f365b9dd2e1aff2651cb7f77bf 100644 (file)
@@ -77,9 +77,9 @@ int db_find_job_start_time(B_DB *mdb, JOB_DBR *jr, char *stime)
    long addr;
 
    strcpy(stime, "0000-00-00 00:00:00");   /* default */
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_jobs_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->jobfd, 0L, SEEK_SET);   /* rewind file */
@@ -132,7 +132,7 @@ StartTime=%100s", &JobId, Name, cType, cLevel, StartTime) == 5) {
         }
       }
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -152,9 +152,9 @@ int db_find_next_volume(B_DB *mdb, int item, MEDIA_DBR *mr)
    int index = 0;
    int len;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_media_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->mediafd, 0L, SEEK_SET);  /* rewind file */
@@ -173,7 +173,7 @@ int db_find_next_volume(B_DB *mdb, int item, MEDIA_DBR *mr)
         break;                       /* found it */
       }
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;                
 }
 
index c33f6acf783fbb340d8f2dab61abb34a7e4ad784..0001233adb0b23866ff33d8a214d3ef2ec6d56b0 100644 (file)
@@ -75,15 +75,15 @@ int db_get_job_record(B_DB *mdb, JOB_DBR *jr)
    int stat = 0;
    int len;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (jr->JobId == 0 && jr->Name[0] == 0) { /* he wants # of Job records */
       jr->JobId = mdb->control.JobId;
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 1;
    }
    Dmsg0(200, "Open Jobs\n");
    if (!bdb_open_jobs_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->jobfd, 0L, SEEK_SET);   /* rewind file */
@@ -117,7 +117,7 @@ int db_get_job_record(B_DB *mdb, JOB_DBR *jr)
    if (!found) {
       strcpy(mdb->errmsg, "Job record not found.\n");
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    Dmsg1(200, "Return job stat=%d\n", stat);
    return stat;
 }
@@ -133,9 +133,9 @@ int db_get_num_pool_records(B_DB *mdb)
 {
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    stat = mdb->control.PoolId;
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -153,10 +153,10 @@ int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
    POOL_DBR opr;
    int len;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    *ids = NULL;
    if (!bdb_open_pools_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->poolfd, 0L, SEEK_SET);   /* rewind file */
@@ -169,7 +169,7 @@ int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
       id[i++] = opr.PoolId;
    }
    *ids = id;
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -190,10 +190,10 @@ int db_get_pool_record(B_DB *mdb, POOL_DBR *pr)
    int stat = 0;
    int len;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Dmsg0(200, "Open pools\n");
    if (!bdb_open_pools_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->poolfd, 0L, SEEK_SET);   /* rewind file */
@@ -227,7 +227,7 @@ int db_get_pool_record(B_DB *mdb, POOL_DBR *pr)
    if (!found) {
       strcpy(mdb->errmsg, "Pool record not found.\n");
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    Dmsg1(200, "Return pool stat=%d\n", stat);
    return stat;
 }
@@ -242,9 +242,9 @@ int db_get_num_media_records(B_DB *mdb)
 {
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    stat = mdb->control.MediaId;
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -262,10 +262,10 @@ int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
    MEDIA_DBR omr;
    int len;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    *ids = NULL;
    if (!bdb_open_media_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->mediafd, 0L, SEEK_SET);  /* rewind file */
@@ -278,7 +278,7 @@ int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
       id[i++] = omr.MediaId;
    }
    *ids = id;
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -298,9 +298,9 @@ int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr)
    int len;
    MEDIA_DBR omr;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_media_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->mediafd, 0L, SEEK_SET);  /* rewind file */
@@ -338,7 +338,7 @@ int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr)
    if (stat == 0) {
       strcpy(mdb->errmsg, "Could not find requested Media record.\n");
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -356,13 +356,13 @@ int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, char *VolumeNames)
    MEDIA_DBR mr;
    int jmlen, mrlen;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_jobmedia_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    if (!bdb_open_media_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    jmlen = sizeof(jm);
@@ -387,7 +387,7 @@ int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, char *VolumeNames)
    if (!found) {
       strcpy(mdb->errmsg, "No Volumes found.\n");
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return found; 
 }
 
@@ -405,9 +405,9 @@ int db_get_client_record(B_DB *mdb, CLIENT_DBR *cr)
    int len;
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_client_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->clientfd, 0L, SEEK_SET);  /* rewind file */
@@ -434,7 +434,7 @@ int db_get_client_record(B_DB *mdb, CLIENT_DBR *cr)
    if (!stat) {
       strcpy(mdb->errmsg, "Client record not found.\n");
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -451,9 +451,9 @@ int db_get_fileset_record(B_DB *mdb, FILESET_DBR *fsr)
    FILESET_DBR lfsr;
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_fileset_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    fseek(mdb->filesetfd, 0L, SEEK_SET);   /* rewind file */
@@ -481,7 +481,7 @@ int db_get_fileset_record(B_DB *mdb, FILESET_DBR *fsr)
    if (!stat) {
       strcpy(mdb->errmsg, "FileSet record not found.\n");
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
index 48af9c26d2a8395f40efcc7c46e17782c9511d31..99a00b214a70cd91f62c4963428ce5625bfd93d6 100644 (file)
@@ -73,9 +73,9 @@ void db_list_pool_records(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx)
    POOL_DBR pr;
 
    Dmsg0(90, "Enter list_pool_records\n");
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_pools_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
    sendit(ctx, "  PoolId NumVols MaxVols  Type       PoolName\n");
@@ -88,7 +88,7 @@ void db_list_pool_records(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx)
         sendit(ctx, mdb->cmd);
    }
    sendit(ctx, "===================================================\n");
-   V(mdb->mutex);
+   db_unlock(mdb);
    Dmsg0(90, "Leave list_pool_records\n");
    return;
 }
@@ -103,9 +103,9 @@ void db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit,
    int len;
    MEDIA_DBR mr;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_media_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
    sendit(ctx, "  Status           VolBytes  MediaType        VolumeName\n");
@@ -119,7 +119,7 @@ void db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit,
         sendit(ctx, mdb->cmd);
    }
    sendit(ctx, "====================================================================\n");
-   V(mdb->mutex);
+   db_unlock(mdb);
    return;
 }
 
@@ -129,13 +129,13 @@ void db_list_jobmedia_records(B_DB *mdb, uint32_t JobId, DB_LIST_HANDLER *sendit
    MEDIA_DBR mr;
    int jmlen, mrlen;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_jobmedia_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
    if (!bdb_open_media_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
    sendit(ctx, "    JobId VolumeName    FirstIndex LastIndex\n");
@@ -173,7 +173,7 @@ void db_list_jobmedia_records(B_DB *mdb, uint32_t JobId, DB_LIST_HANDLER *sendit
    }
 
    sendit(ctx, "============================================\n");
-   V(mdb->mutex);
+   db_unlock(mdb);
    return;
 }
 
@@ -190,9 +190,9 @@ void db_list_job_records(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *
    char dt[MAX_TIME_LENGTH];
    struct tm tm;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_jobs_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
    fseek(mdb->jobfd, 0L, SEEK_SET);   /* rewind file */
@@ -220,7 +220,7 @@ void db_list_job_records(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *
       sendit(ctx, mdb->cmd);
    }
    sendit(ctx, "============================================================================\n");
-   V(mdb->mutex);
+   db_unlock(mdb);
    return;
 }
 
@@ -237,9 +237,9 @@ void db_list_job_totals(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *c
    uint64_t total_files = 0;
    uint32_t total_jobs = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!bdb_open_jobs_file(mdb)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
    fseek(mdb->jobfd, 0L, SEEK_SET);   /* rewind file */
@@ -260,7 +260,7 @@ void db_list_job_totals(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *c
             edit_uint64_with_commas(total_bytes, ewc3));
    sendit(ctx, mdb->cmd);
    sendit(ctx, "=======================================\n");
-   V(mdb->mutex);
+   db_unlock(mdb);
    return;
 }
 
index 00bed656bf61d7763efb859c1f2239c5cd30764d..8b0f0ea2f503489f4838b80587f7423067a24d2e 100755 (executable)
@@ -74,7 +74,7 @@ int db_update_job_start_record(B_DB *mdb, JOB_DBR *jr)
       return 0;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
 
    fseek(mdb->jobfd, ojr.rec_addr, SEEK_SET);
    if (fwrite(jr, len, 1, mdb->jobfd) != 1) {
@@ -83,7 +83,7 @@ int db_update_job_start_record(B_DB *mdb, JOB_DBR *jr)
    }
    fflush(mdb->jobfd);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -104,7 +104,7 @@ int db_update_job_end_record(B_DB *mdb, JOB_DBR *jr)
       return 0;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
 
    fseek(mdb->jobfd, ojr.rec_addr, SEEK_SET);
    if (fwrite(jr, len, 1, mdb->jobfd) != 1) {
@@ -113,7 +113,7 @@ int db_update_job_end_record(B_DB *mdb, JOB_DBR *jr)
    }
    fflush(mdb->jobfd);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -133,7 +133,7 @@ int db_update_media_record(B_DB *mdb, MEDIA_DBR *mr)
       return 0;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
 
    /* Don't allow some fields to change by copying from master record */
    strcpy(mr->VolumeName, omr.VolumeName);
@@ -151,7 +151,7 @@ int db_update_media_record(B_DB *mdb, MEDIA_DBR *mr)
    }
    fflush(mdb->mediafd);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -169,7 +169,7 @@ int db_update_pool_record(B_DB *mdb, POOL_DBR *pr)
       return 0;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
 
    /* Update specific fields */
    opr.NumVols = pr->NumVols;
@@ -188,7 +188,7 @@ int db_update_pool_record(B_DB *mdb, POOL_DBR *pr)
    }
    fflush(mdb->poolfd);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
index b01d416d468b1785a052215dc5ff41dd9d87898b..392bbc24ba7490f74bb9c31356f5feba918d358a 100644 (file)
 
 #ifndef __SQL_H_
 #define __SQL_H_ 1
+
 
 typedef void (DB_LIST_HANDLER)(void *, char *);
 typedef int (DB_RESULT_HANDLER)(void *, int, char **);
+
+#define db_lock(mdb)   _db_lock(__FILE__, __LINE__, mdb)
+#define db_unlock(mdb) _db_unlock(__FILE__, __LINE__, mdb)
+
+#ifdef xxxxx_old_way_of_doing_it
+#define db_lock(mdb)   P(mdb->mutex)
+#define db_unlock(mdb) V(mdb->mutex)
+#define db_lock(mdb) \
+   do { int errstat; if ((errstat=rwl_writelock(&(mdb->lock)))) \
+      e_msg(__FILE__, __LINE__, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",\
+           strerror(errstat)); \
+   } while(0)
+
+#define db_unlock(x) \
+   do { int errstat; if ((errstat=rwl_writeunlock(&(mdb->lock)))) \
+         e_msg(__FILE__, __LINE__, M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",\
+           strerror(errstat)); \
+   } while(0)
+#endif
+
  
 #ifdef __SQL_C
 
@@ -54,57 +74,58 @@ struct sqlite {
    char dummy;
 };
 
-#define IS_NUM(x)            ((x) == 1)
-#define IS_NOT_NULL(x)       ((x) == 1)
+#define IS_NUM(x)             ((x) == 1)
+#define IS_NOT_NULL(x)        ((x) == 1)
 
 typedef struct s_sql_field {
-   char *name;                       /* name of column */
-   uint32_t length;                  /* length */
-   uint32_t max_length;              /* max length */
-   uint32_t type;                    /* type */
-   uint32_t flags;                   /* flags */
+   char *name;                        /* name of column */
+   uint32_t length;                   /* length */
+   uint32_t max_length;               /* max length */
+   uint32_t type;                     /* type */
+   uint32_t flags;                    /* flags */
 } SQL_FIELD;
 
 /*
  * This is the "real" definition that should only be
  * used inside sql.c and associated database interface
  * subroutines.
- *                   S Q L I T E
+ *                    S Q L I T E
  */
 typedef struct s_db {
-   BQUEUE bq;                        /* queue control */
-   pthread_mutex_t mutex;
+   BQUEUE bq;                         /* queue control */
+/* pthread_mutex_t mutex; */
+   rwlock_t lock;                     /* transaction lock */
    struct sqlite *db;
    char **result;
-   int nrow;                         /* nrow returned from sqlite */
-   int ncolumn;                      /* ncolum returned from sqlite */
-   int num_rows;                     /* used by code */
-   int row;                          /* seek row */
-   int have_insert_id;               /* do not have insert id */
-   int fields_defined;               /* set when fields defined */
-   int field;                        /* seek field */
-   SQL_FIELD **fields;               /* defined fields */
+   int nrow;                          /* nrow returned from sqlite */
+   int ncolumn;                       /* ncolum returned from sqlite */
+   int num_rows;                      /* used by code */
+   int row;                           /* seek row */
+   int have_insert_id;                /* do not have insert id */
+   int fields_defined;                /* set when fields defined */
+   int field;                         /* seek field */
+   SQL_FIELD **fields;                /* defined fields */
    int ref_count;
    char *db_name;
    char *db_user;
    char *db_password;
    int connected;
-   char *sqlite_errmsg;              /* error message returned by sqlite */
-   char *errmsg;                     /* nicely edited error message */
-   char *cmd;                        /* SQL command string */
+   char *sqlite_errmsg;               /* error message returned by sqlite */
+   POOLMEM *errmsg;                   /* nicely edited error message */
+   POOLMEM *cmd;                      /* SQL command string */
 } B_DB;
 
 
 /* 
  * "Generic" names for easier conversion   
  *
- *                   S Q L I T E
+ *                    S Q L I T E
  */
 #define sql_store_result(x)   x->result
 #define sql_free_result(x)    my_sqlite_free_table(x)
 #define sql_fetch_row(x)      my_sqlite_fetch_row(x)
 #define sql_query(x, y)       my_sqlite_query(x, y)
-#define sql_close(x)         sqlite_close(x->db)  
+#define sql_close(x)          sqlite_close(x->db)  
 #define sql_strerror(x)       x->sqlite_errmsg?x->sqlite_errmsg:"unknown"
 #define sql_num_rows(x)       x->nrow
 #define sql_data_seek(x, i)   x->row = i
@@ -113,7 +134,7 @@ typedef struct s_db {
 #define sql_field_seek(x, y)  my_sqlite_field_seek(x, y)
 #define sql_fetch_field(x)    my_sqlite_fetch_field(x)
 #define sql_num_fields(x)     (unsigned)((x)->ncolumn)
-#define SQL_ROW              char**   
+#define SQL_ROW               char**   
 
 
 
@@ -135,11 +156,12 @@ extern void my_sqlite_free_table(B_DB *mdb);
  * used inside sql.c and associated database interface
  * subroutines.
  *
- *                    M Y S Q L
+ *                     M Y S Q L
  */
 typedef struct s_db {
-   BQUEUE bq;                        /* queue control */
-   pthread_mutex_t mutex;
+   BQUEUE bq;                         /* queue control */
+/* pthread_mutex_t mutex; */
+   rwlock_t lock;                     /* transaction lock */
    MYSQL mysql;
    MYSQL *db;
    MYSQL_RES *result;
@@ -148,10 +170,10 @@ typedef struct s_db {
    char *db_name;
    char *db_user;
    char *db_password;
-   int have_insert_id;               /* do have insert_id() */
+   int have_insert_id;                /* do have insert_id() */
    int connected;
-   char *errmsg;                     /* nicely edited error message */
-   char *cmd;                        /* SQL command string */
+   POOLMEM *errmsg;                   /* nicely edited error message */
+   POOLMEM *cmd;                      /* SQL command string */
 } B_DB;
 
 
@@ -160,7 +182,7 @@ typedef struct s_db {
 #define sql_free_result(x)    mysql_free_result(x->result)
 #define sql_fetch_row(x)      mysql_fetch_row(x->result)
 #define sql_query(x, y)       mysql_query(x->db, y)
-#define sql_close(x)         mysql_close(x->db)  
+#define sql_close(x)          mysql_close(x->db)  
 #define sql_strerror(x)       mysql_error(x->db)
 #define sql_num_rows(x)       mysql_num_rows(x->result)
 #define sql_data_seek(x, i)   mysql_data_seek(x->result, i)
@@ -169,8 +191,8 @@ typedef struct s_db {
 #define sql_field_seek(x, y)  mysql_field_seek(x->result, y)
 #define sql_fetch_field(x)    mysql_fetch_field(x->result)
 #define sql_num_fields(x)     mysql_num_fields(x->result)
-#define SQL_ROW              MYSQL_ROW
-#define SQL_FIELD            MYSQL_FIELD
+#define SQL_ROW               MYSQL_ROW
+#define SQL_FIELD             MYSQL_FIELD
 
 #else  /* USE BACULA DB routines */
 
@@ -179,17 +201,17 @@ typedef struct s_db {
 /* Change this each time there is some incompatible
  * file format change!!!!
  */
-#define BDB_VERSION 8                /* file version number */
+#define BDB_VERSION                 /* file version number */
 
 struct s_control {
-   int bdb_version;                  /* Version number */
-   uint32_t JobId;                   /* next Job Id */
-   uint32_t PoolId;                  /* next Pool Id */
-   uint32_t MediaId;                 /* next Media Id */
-   uint32_t JobMediaId;              /* next JobMedia Id */
-   uint32_t ClientId;                /* next Client Id */
-   uint32_t FileSetId;               /* nest FileSet Id */
-   time_t time;                      /* time file written */
+   int bdb_version;                   /* Version number */
+   uint32_t JobId;                    /* next Job Id */
+   uint32_t PoolId;                   /* next Pool Id */
+   uint32_t MediaId;                  /* next Media Id */
+   uint32_t JobMediaId;               /* next JobMedia Id */
+   uint32_t ClientId;                 /* next Client Id */
+   uint32_t FileSetId;                /* nest FileSet Id */
+   time_t time;                       /* time file written */
 };
 
 
@@ -197,20 +219,21 @@ struct s_control {
  *  Bacula internal DB
  */
 typedef struct s_db {
-   BQUEUE bq;                        /* queue control */
-   pthread_mutex_t mutex;            /* single thread lock */
-   int ref_count;                    /* number of times opened */
-   struct s_control control;         /* control file structure */
-   int cfd;                          /* control file device */
-   FILE *jobfd;                      /* Jobs records file descriptor */
-   FILE *poolfd;                     /* Pool records fd */
-   FILE *mediafd;                    /* Media records fd */
-   FILE *jobmediafd;                 /* JobMedia records fd */
-   FILE *clientfd;                   /* Client records fd */
-   FILE *filesetfd;                  /* FileSet records fd */
-   char *db_name;                    /* name of database */
-   char *errmsg;                     /* nicely edited error message */
-   char *cmd;                        /* Command string */
+   BQUEUE bq;                         /* queue control */
+/* pthread_mutex_t mutex;  */         /* single thread lock */
+   rwlock_t lock;                     /* transaction lock */
+   int ref_count;                     /* number of times opened */
+   struct s_control control;          /* control file structure */
+   int cfd;                           /* control file device */
+   FILE *jobfd;                       /* Jobs records file descriptor */
+   FILE *poolfd;                      /* Pool records fd */
+   FILE *mediafd;                     /* Media records fd */
+   FILE *jobmediafd;                  /* JobMedia records fd */
+   FILE *clientfd;                    /* Client records fd */
+   FILE *filesetfd;                   /* FileSet records fd */
+   char *db_name;                     /* name of database */
+   POOLMEM *errmsg;                   /* nicely edited error message */
+   POOLMEM *cmd;                      /* Command string */
 } B_DB;
 
 #endif /* HAVE_MYSQL */
@@ -223,19 +246,19 @@ typedef struct s_db {
 #define DELETE_DB(db, cmd) DeleteDB(__FILE__, __LINE__, db, cmd)
 
 
-#else   /* not __SQL_C */
+#else    /* not __SQL_C */
 
 /* This is a "dummy" definition for use outside of sql.c
  */
-typedef struct s_db {    
-   int dummy;                        /* for SunOS compiler */
+typedef struct s_db {     
+   int dummy;                         /* for SunOS compiler */
 } B_DB;  
 
 #endif /*  __SQL_C */
 
 /* ***FIXME*** FileId_t should be uint64_t */
 typedef uint32_t FileId_t;
-typedef uint32_t DBId_t;             /* general DB id type */
+typedef uint32_t DBId_t;              /* general DB id type */
 typedef uint32_t JobId_t;
 
 
@@ -247,18 +270,18 @@ typedef uint32_t JobId_t;
 /* Job record */
 typedef struct {
    JobId_t JobId;
-   char Job[MAX_NAME_LENGTH];        /* Job unique name */
-   char Name[MAX_NAME_LENGTH];       /* Job base name */
-   int Type;                         /* actually char(1) */
-   int Level;                        /* actually char(1) */
-   int JobStatus;                    /* actually char(1) */
-   uint32_t ClientId;                /* Id of client */
-   uint32_t PoolId;                  /* Id of pool */
-   uint32_t FileSetId;               /* Id of FileSet */
-   time_t SchedTime;                 /* Time job scheduled */
-   time_t StartTime;                 /* Job start time */
-   time_t EndTime;                   /* Job termination time */
-   btime_t JobTDate;                 /* Backup time/date in seconds */
+   char Job[MAX_NAME_LENGTH];         /* Job unique name */
+   char Name[MAX_NAME_LENGTH];        /* Job base name */
+   int Type;                          /* actually char(1) */
+   int Level;                         /* actually char(1) */
+   int JobStatus;                     /* actually char(1) */
+   uint32_t ClientId;                 /* Id of client */
+   uint32_t PoolId;                   /* Id of pool */
+   uint32_t FileSetId;                /* Id of FileSet */
+   time_t SchedTime;                  /* Time job scheduled */
+   time_t StartTime;                  /* Job start time */
+   time_t EndTime;                    /* Job termination time */
+   btime_t JobTDate;                  /* Backup time/date in seconds */
    uint32_t VolSessionId;
    uint32_t VolSessionTime;
    uint32_t JobFiles;
@@ -269,8 +292,8 @@ typedef struct {
    /* Note, FirstIndex, LastIndex, Start/End File and Block
     * are only used in the JobMedia record.
     */
-   uint32_t FirstIndex;              /* First index this Volume */
-   uint32_t LastIndex;               /* Last index this Volume */
+   uint32_t FirstIndex;               /* First index this Volume */
+   uint32_t LastIndex;                /* Last index this Volume */
    uint32_t StartFile;
    uint32_t EndFile;
    uint32_t StartBlock;
@@ -288,15 +311,15 @@ typedef struct {
  */
 /* JobMedia record */
 typedef struct {
-   uint32_t JobMediaId;              /* record id */
-   JobId_t  JobId;                   /* JobId */
-   uint32_t MediaId;                 /* MediaId */
-   uint32_t FirstIndex;              /* First index this Volume */
-   uint32_t LastIndex;               /* Last index this Volume */
-   uint32_t StartFile;               /* File for start of data */
-   uint32_t EndFile;                 /* End file on Volume */
-   uint32_t StartBlock;              /* start block on tape */
-   uint32_t EndBlock;                /* last block */
+   uint32_t JobMediaId;               /* record id */
+   JobId_t  JobId;                    /* JobId */
+   uint32_t MediaId;                  /* MediaId */
+   uint32_t FirstIndex;               /* First index this Volume */
+   uint32_t LastIndex;                /* Last index this Volume */
+   uint32_t StartFile;                /* File for start of data */
+   uint32_t EndFile;                  /* End file on Volume */
+   uint32_t StartBlock;               /* start block on tape */
+   uint32_t EndBlock;                 /* last block */
 } JOBMEDIA_DBR;
 
 
@@ -305,9 +328,9 @@ typedef struct {
  *  records (e.g. pathname, filename, fileattributes).
  */
 typedef struct {
-   char *fname;                      /* full path & filename */
-   char *link;                       /* link if any */
-   char *attr;                       /* attributes statp */
+   char *fname;                       /* full path & filename */
+   char *link;                        /* link if any */
+   char *attr;                        /* attributes statp */
    uint32_t FileIndex;
    uint32_t Stream;
    JobId_t  JobId;
@@ -333,16 +356,16 @@ typedef struct {
 /* Pool record -- same format as database */
 typedef struct {
    uint32_t PoolId;
-   char Name[MAX_NAME_LENGTH];       /* Pool name */
-   uint32_t NumVols;                 /* total number of volumes */
-   uint32_t MaxVols;                 /* max allowed volumes */
-   int UseOnce;                      /* set to use once only */
-   int UseCatalog;                   /* set to use catalog */
-   int AcceptAnyVolume;              /* set to accept any volume sequence */
-   int AutoPrune;                    /* set to prune automatically */
-   int Recycle;                      /* default Vol recycle flag */
-   btime_t VolRetention;             /* retention period in seconds */
-   char PoolType[MAX_NAME_LENGTH];            
+   char Name[MAX_NAME_LENGTH];        /* Pool name */
+   uint32_t NumVols;                  /* total number of volumes */
+   uint32_t MaxVols;                  /* max allowed volumes */
+   int UseOnce;                       /* set to use once only */
+   int UseCatalog;                    /* set to use catalog */
+   int AcceptAnyVolume;               /* set to accept any volume sequence */
+   int AutoPrune;                     /* set to prune automatically */
+   int Recycle;                       /* default Vol recycle flag */
+   btime_t VolRetention;              /* retention period in seconds */
+   char PoolType[MAX_NAME_LENGTH];             
    char LabelFormat[MAX_NAME_LENGTH];
    /* Extra stuff not in DB */
    faddr_t rec_addr;
@@ -350,51 +373,49 @@ typedef struct {
 
 /* Media record -- same as the database */
 typedef struct {
-   uint32_t MediaId;                 /* Unique volume id */
+   uint32_t MediaId;                  /* Unique volume id */
    char VolumeName[MAX_NAME_LENGTH];  /* Volume name */
    char MediaType[MAX_NAME_LENGTH];   /* Media type */
-   uint32_t PoolId;                  /* Pool id */
-   time_t FirstWritten;              /* Time Volume first written */
-   time_t LastWritten;               /* Time Volume last written */
-   time_t LabelDate;                 /* Date/Time Volume labelled */
-   uint32_t VolJobs;                 /* number of jobs on this medium */
-   uint32_t VolFiles;                /* Number of files */
-   uint32_t VolBlocks;               /* Number of blocks */
-   uint32_t VolMounts;               /* Number of times mounted */
-   uint32_t VolErrors;               /* Number of read/write errors */
-   uint32_t VolWrites;               /* Number of writes */
-   uint32_t VolReads;                /* Number of reads */
-   uint64_t VolBytes;                /* Number of bytes written */
-   uint64_t VolMaxBytes;             /* max bytes to write */
-   uint64_t VolCapacityBytes;        /* capacity estimate */
-   btime_t  VolRetention;            /* Volume retention in seconds */
-   int Recycle;                      /* recycle yes/no */
-   char VolStatus[20];               /* Volume status */
+   uint32_t PoolId;                   /* Pool id */
+   time_t FirstWritten;               /* Time Volume first written */
+   time_t LastWritten;                /* Time Volume last written */
+   time_t LabelDate;                  /* Date/Time Volume labelled */
+   uint32_t VolJobs;                  /* number of jobs on this medium */
+   uint32_t VolFiles;                 /* Number of files */
+   uint32_t VolBlocks;                /* Number of blocks */
+   uint32_t VolMounts;                /* Number of times mounted */
+   uint32_t VolErrors;                /* Number of read/write errors */
+   uint32_t VolWrites;                /* Number of writes */
+   uint32_t VolReads;                 /* Number of reads */
+   uint64_t VolBytes;                 /* Number of bytes written */
+   uint64_t VolMaxBytes;              /* max bytes to write */
+   uint64_t VolCapacityBytes;         /* capacity estimate */
+   btime_t  VolRetention;             /* Volume retention in seconds */
+   int Recycle;                       /* recycle yes/no */
+   char VolStatus[20];                /* Volume status */
    /* Extra stuff not in DB */
-   faddr_t rec_addr;                 /* found record address */
+   faddr_t rec_addr;                  /* found record address */
 } MEDIA_DBR;
 
 /* Client record -- same as the database */
 typedef struct {
-   uint32_t ClientId;                /* Unique Client id */
+   uint32_t ClientId;                 /* Unique Client id */
    int AutoPrune;
    btime_t FileRetention;
    btime_t JobRetention;
-   char Name[MAX_NAME_LENGTH];       /* Client name */
-   char Uname[256];                  /* Uname for client */
+   char Name[MAX_NAME_LENGTH];        /* Client name */
+   char Uname[256];                   /* Uname for client */
 } CLIENT_DBR;
 
 /* FileSet record -- same as the database */
 typedef struct {
-   uint32_t FileSetId;               /* Unique FileSet id */
+   uint32_t FileSetId;                /* Unique FileSet id */
    char FileSet[MAX_NAME_LENGTH];     /* FileSet name */
-   char MD5[50];                     /* MD5 signature of include/exclude */
+   char MD5[50];                      /* MD5 signature of include/exclude */
 } FILESET_DBR;
 
 
-
 #include "protos.h"
-
 #include "jcr.h"
-
 #endif /* __SQL_H_ */
index 638978277022ebfbe6a6d7be3f2d38b4558a02ec..a35e21d6c8c73d9d95489481bdf870be8645473a 100644 (file)
@@ -77,9 +77,9 @@ db_init_database(char *db_name, char *db_user, char *db_password)
    mdb->db_user = bstrdup(db_user);
    mdb->db_password = bstrdup(db_password);
    mdb->have_insert_id = TRUE;
-   mdb->errmsg = (char *) get_pool_memory(PM_EMSG); /* get error message buffer */
+   mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
    *mdb->errmsg = 0;
-   mdb->cmd = (char *) get_pool_memory(PM_EMSG);    /* get command buffer */
+   mdb->cmd = get_pool_memory(PM_EMSG);    /* get command buffer */
    mdb->ref_count = 1;
    qinsert(&db_list, &mdb->bq);           /* put db in list */
    V(mutex);
@@ -99,11 +99,19 @@ db_open_database(B_DB *mdb)
       return 1;
    }
    mdb->connected = FALSE;
+#ifdef needed
    if (pthread_mutex_init(&mdb->mutex, NULL) != 0) {
       Mmsg1(&mdb->errmsg, "Unable to initialize DB mutex. ERR=%s\n", strerror(errno));
       V(mutex);
       return 0;
    }
+#endif
+
+   if (rwl_init(&mdb->lock) != 0) {
+      Mmsg1(&mdb->errmsg, "Unable to initialize DB lock. ERR=%s\n", strerror(errno));
+      V(mutex);
+      return 0;
+   }
 
    /* connect to the database */
    mysql_init(&(mdb->mysql));
@@ -164,7 +172,8 @@ db_close_database(B_DB *mdb)
       if (mdb->connected && mdb->db) {
         sql_close(mdb);
       }
-      pthread_mutex_destroy(&mdb->mutex);
+/*    pthread_mutex_destroy(&mdb->mutex); */
+      rwl_destroy(&mdb->lock);      
       free_pool_memory(mdb->errmsg);
       free_pool_memory(mdb->cmd);
       if (mdb->db_name) {
@@ -209,10 +218,10 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void
 {
    SQL_ROW row;
   
-   P(mdb->mutex);
+   db_lock(mdb);
    if (sql_query(mdb, query) != 0) {
       Mmsg(&mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    if (result_handler != NULL) {
@@ -227,7 +236,7 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void
         sql_free_result(mdb);
       }
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 
 }
index 0c3a95f63860deb9dc927bb56b08788d61552160..cea777bd3475af791d653c24972ccb2d2fcbb501 100644 (file)
@@ -39,6 +39,8 @@ int get_sql_record_max(B_DB *mdb);
 char *db_next_index(B_DB *mdb, char *table);
 int db_sql_query(B_DB *mdb, char *cmd, DB_RESULT_HANDLER *result_handler, void *ctx);
 int check_tables_version(B_DB *mdb);
+void _db_unlock(char *file, int line, B_DB *mdb);
+void _db_lock(char *file, int line, B_DB *mdb);
 
 /* create.c */
 int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar);
index 6924de8df97cb67f57f21cdeada7b6a85eaea0fe..54366045d85c9b8c7c176d0ed21bb7dac0f18e83 100644 (file)
@@ -198,4 +198,23 @@ char *db_strerror(B_DB *mdb)
    return mdb->errmsg;
 }
 
+void _db_lock(char *file, int line, B_DB *mdb)
+{
+   int errstat;
+   if ((errstat=rwl_writelock(&mdb->lock)) != 0) {
+      e_msg(file, line, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
+          strerror(errstat));
+   }
+}    
+
+void _db_unlock(char *file, int line, B_DB *mdb)
+{
+   int errstat;
+   if ((errstat=rwl_writeunlock(&mdb->lock)) != 0) {
+      e_msg(file, line, M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
+          strerror(errstat));
+   }
+}    
+
+
 #endif /* HAVE_MYSQL | HAVE_SQLITE */
index 7f10ba49cbc87473ab6e432cdd069ec567c00962..77dfa27a0b9ed176135ad1cfc98c0bb6252a4251 100644 (file)
@@ -79,11 +79,11 @@ db_create_job_record(B_DB *mdb, JOB_DBR *jr)
    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
    JobTDate = (btime_t)stime;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    JobId = db_next_index(mdb, "Job");
    if (!JobId) {
       jr->JobId = 0;
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    /* Must create it */
@@ -102,7 +102,7 @@ db_create_job_record(B_DB *mdb, JOB_DBR *jr)
       jr->JobId = sql_insert_id(mdb);
       stat = 1;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -115,7 +115,7 @@ db_create_jobmedia_record(B_DB *mdb, JOBMEDIA_DBR *jm)
 {
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT JobId, MediaId FROM JobMedia WHERE \
 JobId=%d AND MediaId=%d", jm->JobId, jm->MediaId);
 
@@ -125,7 +125,7 @@ JobId=%d AND MediaId=%d", jm->JobId, jm->MediaId);
       if (mdb->num_rows > 0) {
          Mmsg0(&mdb->errmsg, _("Create JobMedia failed. Record already exists.\n"));
         sql_free_result(mdb);
-        V(mdb->mutex);
+        db_unlock(mdb);
          Dmsg0(0, "Already have JobMedia record\n");
         return 0;
       }
@@ -146,7 +146,7 @@ VALUES (%d, %d, %u, %u)",
    } else {
       stat = 1;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    Dmsg0(30, "Return from JobMedia\n");
    return stat;
 }
@@ -163,7 +163,7 @@ db_create_pool_record(B_DB *mdb, POOL_DBR *pr)
    int stat;
    char ed1[30];
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT PoolId,Name FROM Pool WHERE Name=\"%s\"", pr->Name);
    Dmsg1(20, "selectpool: %s\n", mdb->cmd);
 
@@ -174,7 +174,7 @@ db_create_pool_record(B_DB *mdb, POOL_DBR *pr)
       if (mdb->num_rows > 0) {
          Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pr->Name);
         sql_free_result(mdb);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 0;
       }
       sql_free_result(mdb);
@@ -202,7 +202,7 @@ VALUES (\"%s\", %d, %d, %d, %d, %d, %d, %d, %s, \"%s\", \"%s\")",
       pr->PoolId = sql_insert_id(mdb);
       stat = 1;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    
    return stat;
 }
@@ -219,7 +219,7 @@ db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
    int stat;
    char ed1[30], ed2[30], ed3[30];
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT MediaId FROM Media WHERE VolumeName=\"%s\"", 
           mr->VolumeName);
    Dmsg1(110, "selectpool: %s\n", mdb->cmd);
@@ -229,7 +229,7 @@ db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
       if (mdb->num_rows > 0) {
          Mmsg1(&mdb->errmsg, _("Media record %s already exists\n"), mr->VolumeName);
         sql_free_result(mdb);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 0;
       }
       sql_free_result(mdb);
@@ -256,7 +256,7 @@ Recycle, VolRetention, VolStatus) VALUES (\"%s\", \"%s\", %d, %s, %s, %d, %s, \"
       mr->MediaId = sql_insert_id(mdb);
       stat = 1;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -273,7 +273,7 @@ int db_create_client_record(B_DB *mdb, CLIENT_DBR *cr)
    int stat;
    char ed1[30], ed2[30];
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT ClientId FROM Client WHERE Name=\"%s\"", cr->Name);
 
    cr->ClientId = 0;
@@ -289,14 +289,13 @@ int db_create_client_record(B_DB *mdb, CLIENT_DBR *cr)
       if (mdb->num_rows >= 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching Client row: %s\n"), sql_strerror(mdb));
-           Emsg0(M_ERROR, 0, mdb->errmsg);
            sql_free_result(mdb);
-           V(mdb->mutex);
+           db_unlock(mdb);
            return 0;
         }
         sql_free_result(mdb);
         cr->ClientId = atoi(row[0]);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 1;
       }
       sql_free_result(mdb);
@@ -318,7 +317,7 @@ FileRetention, JobRetention) VALUES \
       cr->ClientId = sql_insert_id(mdb);
       stat = 1;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -334,7 +333,7 @@ int db_create_fileset_record(B_DB *mdb, FILESET_DBR *fsr)
    SQL_ROW row;
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT FileSetId FROM FileSet WHERE \
 FileSet=\"%s\" and MD5=\"%s\"", fsr->FileSet, fsr->MD5);
 
@@ -350,14 +349,13 @@ FileSet=\"%s\" and MD5=\"%s\"", fsr->FileSet, fsr->MD5);
       if (mdb->num_rows >= 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching FileSet row: ERR=%s\n"), sql_strerror(mdb));
-           Emsg0(M_ERROR, 0, mdb->errmsg);
            sql_free_result(mdb);
-           V(mdb->mutex);
+           db_unlock(mdb);
            return 0;
         }
         sql_free_result(mdb);
         fsr->FileSetId = atoi(row[0]);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 1;
       }
       sql_free_result(mdb);
@@ -377,7 +375,7 @@ FileSet=\"%s\" and MD5=\"%s\"", fsr->FileSet, fsr->MD5);
       stat = 1;
    }
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -512,7 +510,7 @@ static int db_create_file_record(B_DB *mdb, ATTR_DBR *ar)
 {
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    /* Must create it */
    Mmsg(&mdb->cmd,
 "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \
@@ -523,14 +521,13 @@ LStat, MD5) VALUES (%d, %d, %d, %d, \"%s\", \"0\")",
    if (!INSERT_DB(mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create db File record %s failed. ERR=%s"),       
         mdb->cmd, sql_strerror(mdb));
-      Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
       ar->FileId = 0;
       stat = 0;
    } else {
       ar->FileId = sql_insert_id(mdb);
       stat = 1;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -544,16 +541,15 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
 
    if (*path == 0) {
       Mmsg0(&mdb->errmsg, _("Null path given to db_create_path_record\n"));
-      Emsg0(M_ERROR, 0, mdb->errmsg);
       ar->PathId = 0;
       return 0;
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
 
    if (cached_id != 0 && strcmp(cached_path, path) == 0) {
       ar->PathId = cached_id;
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 1;
    }
 
@@ -572,9 +568,8 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
       }
       if (mdb->num_rows >= 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
-           V(mdb->mutex);
+           db_unlock(mdb);
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
-           Emsg0(M_ERROR, 0, mdb->errmsg);
            sql_free_result(mdb);
            ar->PathId = 0;
            return 0;
@@ -586,7 +581,7 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
            strncpy(cached_path, path, sizeof(cached_path));
            cached_path[sizeof(cached_path)-1] = 0;
         }
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 1;
       }
 
@@ -598,7 +593,6 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
    if (!INSERT_DB(mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"), 
         mdb->cmd, sql_strerror(mdb));
-      Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
       ar->PathId = 0;
       stat = 0;
    } else {
@@ -611,7 +605,7 @@ static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
       strncpy(cached_path, path, sizeof(cached_path));
       cached_path[sizeof(cached_path)-1] = 0;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -621,7 +615,7 @@ static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar, char *fname)
    SQL_ROW row;
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name=\"%s\"", fname);
 
    if (QUERY_DB(mdb, mdb->cmd)) {
@@ -637,14 +631,13 @@ static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar, char *fname)
             Mmsg2(&mdb->errmsg, _("error fetching row for file=%s: ERR=%s\n"), 
                fname, sql_strerror(mdb));
            sql_free_result(mdb);
-           V(mdb->mutex);
-           Emsg0(M_ERROR, 0, mdb->errmsg);
+           db_unlock(mdb);
            ar->FilenameId = 0;
            return 0;
         }
         sql_free_result(mdb);
         ar->FilenameId = atoi(row[0]);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 1;
       }
       sql_free_result(mdb);
@@ -656,7 +649,6 @@ VALUES (\"%s\")", fname);
    if (!INSERT_DB(mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create db Filename record %s failed. ERR=%s\n"), 
            mdb->cmd, sql_strerror(mdb));
-      Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
       ar->FilenameId = 0;
       stat = 0;
    } else {
@@ -664,7 +656,7 @@ VALUES (\"%s\")", fname);
       stat = 1;
    }
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
index aaa0776e33eded90304054d6002095b5eb09874b..c3c51c7bc66019692991c9c98e1f11c37b2858e2 100644 (file)
@@ -65,7 +65,7 @@ db_delete_pool_record(B_DB *mdb, POOL_DBR *pr)
 {
    SQL_ROW row;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT PoolId FROM Pool WHERE Name=\"%s\"", pr->Name);
    Dmsg1(10, "selectpool: %s\n", mdb->cmd);
 
@@ -78,17 +78,18 @@ db_delete_pool_record(B_DB *mdb, POOL_DBR *pr)
       if (mdb->num_rows == 0) {
          Mmsg(&mdb->errmsg, _("No pool record %s exists\n"), pr->Name);
         sql_free_result(mdb);
-        V(mdb->mutex);
+        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);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 0;
       }
       if ((row = sql_fetch_row(mdb)) == NULL) {
-        V(mdb->mutex);
-         Emsg1(M_ABORT, 0, _("Error fetching row %s\n"), sql_strerror(mdb));
+         Mmsg1(&mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb));
+        db_unlock(mdb);
+        return 0;
       }
       pr->PoolId = atoi(row[0]);
       sql_free_result(mdb);
@@ -107,7 +108,7 @@ db_delete_pool_record(B_DB *mdb, POOL_DBR *pr)
    pr->PoolId = DELETE_DB(mdb, mdb->cmd);
    Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
index ef3d89f2b8dd646851775389cef8f4f281cd136e..bc558ac20fa2c272fe266edc37d483fce92a6cb9 100644 (file)
@@ -67,7 +67,7 @@ db_find_job_start_time(B_DB *mdb, JOB_DBR *jr, char *stime)
    int JobId;
 
    strcpy(stime, "0000-00-00 00:00:00");   /* default */
-   P(mdb->mutex);
+   db_lock(mdb);
    /* If no Id given, we must find corresponding job */
    if (jr->JobId == 0) {
       /* Differential is since last Full backup */
@@ -87,19 +87,18 @@ ORDER by StartTime DESC LIMIT 1",
           jr->ClientId);
       } else {
          Mmsg1(&mdb->errmsg, _("Unknown level=%d\n"), jr->Level);
-        Emsg0(M_ERROR, 0, mdb->errmsg);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 0;
       }
       Dmsg1(100, "Submitting: %s\n", mdb->cmd);
       if (!QUERY_DB(mdb, mdb->cmd)) {
-         Emsg1(M_ERROR, 0, _("Query error for start time request: %s\n"), mdb->cmd);
-        V(mdb->mutex);
+         Mmsg1(&mdb->errmsg, _("Query error for start time request: %s\n"), mdb->cmd);
+        db_unlock(mdb);
         return 0;
       }
       if ((row = sql_fetch_row(mdb)) == NULL) {
         sql_free_result(mdb);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return 0;
       }
       JobId = atoi(row[0]);
@@ -112,16 +111,16 @@ ORDER by StartTime DESC LIMIT 1",
    Mmsg(&mdb->cmd, "SELECT StartTime from Job WHERE Job.JobId=%d", JobId);
 
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      Emsg1(M_ERROR, 0, _("Query error for start time request: %s\n"), mdb->cmd);
-      V(mdb->mutex);
+      Mmsg1(&mdb->errmsg, _("Query error for start time request: %s\n"), mdb->cmd);
+      db_unlock(mdb);
       return 0;
    }
 
    if ((row = sql_fetch_row(mdb)) == NULL) {
       *stime = 0;                    /* set EOS */
-      Emsg2(M_ERROR, 0, _("No Job found for JobId=%d: %s\n"), JobId, sql_strerror(mdb));
+      Mmsg2(&mdb->errmsg, _("No Job found for JobId=%d: %s\n"), JobId, sql_strerror(mdb));
       sql_free_result(mdb);
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    Dmsg1(100, "Got start time: %s\n", row[0]);
@@ -129,7 +128,7 @@ ORDER by StartTime DESC LIMIT 1",
 
    sql_free_result(mdb);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -144,9 +143,9 @@ db_find_last_full_verify(B_DB *mdb, JOB_DBR *jr)
    SQL_ROW row;
 
    /* Find last full */
-   P(mdb->mutex);
+   db_lock(mdb);
    if (jr->Level != L_VERIFY_CATALOG) {
-      Emsg2(M_FATAL, 0, _("Expecting Level=%c, got %c\n"), L_VERIFY_CATALOG, jr->Level);
+      Mmsg2(&mdb->errmsg, _("Expecting Level=%c, got %c\n"), L_VERIFY_CATALOG, jr->Level);
       return 0;
    }
    Mmsg(&mdb->cmd, 
@@ -155,13 +154,13 @@ ClientId=%d ORDER by StartTime DESC LIMIT 1",
           JT_VERIFY, L_VERIFY_INIT, jr->Name, jr->ClientId);
 
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
    if ((row = sql_fetch_row(mdb)) == NULL) {
-      Emsg0(M_FATAL, 0, _("No Job found for last full verify.\n"));
+      Mmsg0(&mdb->errmsg, _("No Job found for last full verify.\n"));
       sql_free_result(mdb);
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
 
@@ -170,12 +169,12 @@ ClientId=%d ORDER by StartTime DESC LIMIT 1",
 
    Dmsg1(100, "db_get_last_full_verify: got JobId=%d\n", jr->JobId);
    if (jr->JobId <= 0) {
-      Emsg1(M_FATAL, 0, _("No Verify Job found for: %s\n"), mdb->cmd);
-      V(mdb->mutex);
+      Mmsg1(&mdb->errmsg, _("No Verify Job found for: %s\n"), mdb->cmd);
+      db_unlock(mdb);
       return 0;
    }
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -193,20 +192,22 @@ db_find_next_volume(B_DB *mdb, int item, MEDIA_DBR *mr)
    SQL_ROW row;
    int numrows;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
 VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes \
 FROM Media WHERE PoolId=%d AND MediaType=\"%s\" AND VolStatus=\"%s\" \
 ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus); 
 
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
 
    numrows = sql_num_rows(mdb);
    if (item > numrows) {
-      V(mdb->mutex);
+      Mmsg2(&mdb->errmsg, _("Request for Volume item %d greater than max %d\n"),
+        item, numrows);
+      db_unlock(mdb);
       return 0;
    }
    
@@ -216,9 +217,9 @@ ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus);
    sql_data_seek(mdb, item-1);
 
    if ((row = sql_fetch_row(mdb)) == NULL) {
-      Emsg1(M_ERROR, 0, _("No media record found for item %d.\n"), item);
+      Mmsg1(&mdb->errmsg, _("No Volume record found for item %d.\n"), item);
       sql_free_result(mdb);
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
 
@@ -237,7 +238,7 @@ ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus);
 
    sql_free_result(mdb);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return numrows;
 }
 
index 0de036b7c33fc3f32ea5e07b4507569bf691187e..f1c1a69220a6155b48611eb1be167361e9dc642e 100644 (file)
@@ -126,8 +126,9 @@ static
 int db_get_file_record(B_DB *mdb, FILE_DBR *fdbr)
 {
    SQL_ROW row;
+   int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, 
 "SELECT FileId, LStat, MD5 from File where File.JobId=%d and File.PathId=%d and \
 File.FilenameId=%d", fdbr->JobId, fdbr->PathId, fdbr->FilenameId);
@@ -142,27 +143,24 @@ File.FilenameId=%d", fdbr->JobId, fdbr->PathId, fdbr->FilenameId);
        */
       if (mdb->num_rows > 1) {
          Emsg1(M_WARNING, 0, _("get_file_record want 1 got rows=%d\n"), mdb->num_rows);
-         Emsg1(M_WARNING, 0, "%s\n", mdb->cmd);
+         Emsg1(M_ERROR, 0, "%s\n", mdb->cmd);
       }
       if (mdb->num_rows >= 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
-            Emsg1(M_ERROR, 0, "Error fetching row: %s\n", sql_strerror(mdb));
+            Mmsg1(&mdb->errmsg, "Error fetching row: %s\n", sql_strerror(mdb));
         } else {
            fdbr->FileId = (FileId_t)strtod(row[0], NULL);
            strncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
            fdbr->LStat[sizeof(fdbr->LStat)] = 0;
            strncpy(fdbr->MD5, row[2], sizeof(fdbr->MD5));
            fdbr->MD5[sizeof(fdbr->MD5)] = 0;
-           sql_free_result(mdb);
-           V(mdb->mutex);
-           return 1;
+           stat = 1;
         }
       }
-
       sql_free_result(mdb);
    }
-   V(mdb->mutex);
-   return 0;                         /* failed */
+   db_unlock(mdb);
+   return stat;
 
 }
 
@@ -180,7 +178,7 @@ static int db_get_filename_record(B_DB *mdb, char *fname)
       Emsg0(M_ABORT, 0, mdb->errmsg);
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name=\"%s\"", fname);
    if (QUERY_DB(mdb, mdb->cmd)) {
 
@@ -188,26 +186,24 @@ static int db_get_filename_record(B_DB *mdb, char *fname)
 
       if (mdb->num_rows > 1) {
          Mmsg1(&mdb->errmsg, _("More than one Filename!: %d\n"), (int)(mdb->num_rows));
-        Emsg0(M_FATAL, 0, mdb->errmsg);
       } else if (mdb->num_rows == 1) {
         if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
-           Emsg0(M_FATAL, 0, mdb->errmsg);
-        }
-        FilenameId = atoi(row[0]);
-        if (FilenameId <= 0) {
-            Mmsg2(&mdb->errmsg, _("Create db Filename record %s found bad record: %d\n"),
-              mdb->cmd, FilenameId); 
-           Emsg0(M_ERROR, 0, mdb->errmsg);
+           FilenameId = 0;
+        } else {
+           FilenameId = atoi(row[0]);
+           if (FilenameId <= 0) {
+               Mmsg2(&mdb->errmsg, _("Create db Filename record %s found bad record: %d\n"),
+                 mdb->cmd, FilenameId); 
+           }
         }
         sql_free_result(mdb);
-        V(mdb->mutex);
+        db_unlock(mdb);
         return FilenameId;
-
       }
       sql_free_result(mdb);
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 0;                         /* failed */
 }
 
@@ -218,9 +214,9 @@ static int db_get_filename_record(B_DB *mdb, char *fname)
 static int db_get_path_record(B_DB *mdb, char *path)
 {
    SQL_ROW row;
-   int PathId;
+   uint32_t PathId = 0;
    /*******FIXME***** move into mdb record and allocate */
-   static int cached_id = 0;
+   static uint32_t cached_id = 0;
    static char cached_path[MAXSTRING];
 
    if (*path == 0) {
@@ -230,7 +226,7 @@ static int db_get_path_record(B_DB *mdb, char *path)
       return cached_id;
    }         
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path=\"%s\"", path);
 
    if (QUERY_DB(mdb, mdb->cmd)) {
@@ -240,25 +236,21 @@ static int db_get_path_record(B_DB *mdb, char *path)
       if (mdb->num_rows > 1) {
          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) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
-           Emsg0(M_FATAL, 0, mdb->errmsg);
-        }
-        PathId = atoi(row[0]);
-        if (PathId != cached_id) {
-           cached_id = PathId;
-           strcpy(cached_path, path);
+        } else {
+           PathId = atoi(row[0]);
+           /* Cache path if it will fit in our static buffer */
+           if (PathId != cached_id && strlen(path) < sizeof(cached_path)+2) {
+              cached_id = PathId;
+              strcpy(cached_path, path);
+           }
         }
-        sql_free_result(mdb);
-        V(mdb->mutex);
-        return PathId;
       }
-
       sql_free_result(mdb);
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 0;                         /* failed */
 }
 
@@ -272,7 +264,7 @@ int db_get_job_record(B_DB *mdb, JOB_DBR *jr)
 {
    SQL_ROW row;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (jr->JobId == 0) {
       Mmsg(&mdb->cmd, "SELECT VolSessionId, VolSessionTime, \
 PoolId, StartTime, EndTime, JobFiles, JobBytes, JobTDate, Job \
@@ -284,13 +276,13 @@ FROM Job WHERE JobId=%d", jr->JobId);
     }
 
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;                      /* failed */
    }
    if ((row = sql_fetch_row(mdb)) == NULL) {
       Mmsg1(&mdb->errmsg, _("No Job found for JobId %d\n"), jr->JobId);
       sql_free_result(mdb);
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;                      /* failed */
    }
 
@@ -305,7 +297,7 @@ FROM Job WHERE JobId=%d", jr->JobId);
    strcpy(jr->Job, row[8]);
    sql_free_result(mdb);
 
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -322,7 +314,7 @@ int db_get_job_volume_names(B_DB *mdb, uint32_t JobId, char *VolumeNames)
    int stat = 0;
    int i;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, 
 "SELECT VolumeName FROM JobMedia,Media WHERE JobMedia.JobId=%d \
 AND JobMedia.MediaId=Media.MediaId", JobId);
@@ -352,7 +344,7 @@ AND JobMedia.MediaId=Media.MediaId", JobId);
       }
       sql_free_result(mdb);
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -367,10 +359,10 @@ int db_get_num_pool_records(B_DB *mdb)
 {
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT count(*) from Pool");
    stat = get_sql_record_max(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -388,7 +380,7 @@ int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
    int i = 0;
    uint32_t *id;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    *ids = NULL;
    Mmsg(&mdb->cmd, "SELECT PoolId FROM Pool");
    if (QUERY_DB(mdb, mdb->cmd)) {
@@ -406,7 +398,7 @@ int db_get_pool_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
       Mmsg(&mdb->errmsg, _("Pool id select failed: ERR=%s\n"), sql_strerror(mdb));
       stat = 0;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -423,7 +415,7 @@ int db_get_pool_record(B_DB *mdb, POOL_DBR *pdbr)
    SQL_ROW row;
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (pdbr->PoolId != 0) {              /* find by id */
       Mmsg(&mdb->cmd, 
 "SELECT PoolId, Name, NumVols, MaxVols, UseOnce, UseCatalog, AcceptAnyVolume, \
@@ -442,11 +434,9 @@ PoolType, LabelFormat FROM Pool WHERE Pool.Name=\"%s\"", pdbr->Name);
         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) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
-           Emsg0(M_ERROR, 0, mdb->errmsg);
         } else {
            pdbr->PoolId = atoi(row[0]);
            strcpy(pdbr->Name, row[1]);
@@ -469,7 +459,7 @@ PoolType, LabelFormat FROM Pool WHERE Pool.Name=\"%s\"", pdbr->Name);
       }
       sql_free_result(mdb);
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -484,10 +474,10 @@ int db_get_num_media_records(B_DB *mdb)
 {
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "SELECT count(*) from Media");
    stat = get_sql_record_max(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -506,7 +496,7 @@ int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
    int i = 0;
    uint32_t *id;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    *ids = NULL;
    Mmsg(&mdb->cmd, "SELECT MediaId FROM Media");
    if (QUERY_DB(mdb, mdb->cmd)) {
@@ -524,7 +514,7 @@ int db_get_media_ids(B_DB *mdb, int *num_ids, uint32_t *ids[])
       Mmsg(&mdb->errmsg, _("Media id select failed: ERR=%s\n"), sql_strerror(mdb));
       stat = 0;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -539,17 +529,17 @@ int db_get_media_record(B_DB *mdb, MEDIA_DBR *mr)
    SQL_ROW row;
    int stat = 0;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (mr->MediaId == 0 && mr->VolumeName[0] == 0) {
       Mmsg(&mdb->cmd, "SELECT count(*) from Media");
       mr->MediaId = get_sql_record_max(mdb);
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 1;
    }
    if (mr->MediaId != 0) {              /* find by id */
       Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
 VolBytes,VolMounts,VolErrors,VolWrites,VolMaxBytes,VolCapacityBytes,\
-MediaType,VolStatus,PoolId,VoRetention,Recycle \
+MediaType,VolStatus,PoolId,VolRetention,Recycle \
 FROM Media WHERE MediaId=%d", mr->MediaId);
    } else {                          /* find by name */
       Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
@@ -564,11 +554,9 @@ FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName);
         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) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
-           Emsg0(M_ERROR, 0, mdb->errmsg);
         } else {
            /* return values */
            mr->MediaId = atoi(row[0]);
@@ -594,7 +582,7 @@ FROM Media WHERE VolumeName=\"%s\"", mr->VolumeName);
       }
       sql_free_result(mdb);
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
index c2197b69bf0a53ee817e82e15bb077b9b53bd4fe..305fc92aabc6f665d0174da0a65d126a95ac0bfe 100644 (file)
@@ -53,11 +53,11 @@ extern int QueryDB(char *file, int line, B_DB *db, char *select_cmd);
  */
 int db_list_sql_query(B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, void *ctx)
 {
-   P(mdb->mutex);
+   db_lock(mdb);
    if (sql_query(mdb, query) != 0) {
       Mmsg(&mdb->errmsg, _("Query failed: %s\n"), sql_strerror(mdb));
       sendit(ctx, mdb->errmsg);
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
 
@@ -67,7 +67,7 @@ int db_list_sql_query(B_DB *mdb, char *query, DB_LIST_HANDLER *sendit, void *ctx
       list_result(mdb, sendit, ctx);
       sql_free_result(mdb);
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
@@ -77,16 +77,16 @@ db_list_pool_records(B_DB *mdb, DB_LIST_HANDLER *sendit, void *ctx)
    Mmsg(&mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,PoolType,LabelFormat \
 FROM Pool");
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
 
    list_result(mdb, sendit, ctx);
    
    sql_free_result(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
 }
 
 void
@@ -97,16 +97,16 @@ db_list_media_records(B_DB *mdb, MEDIA_DBR *mdbr, DB_LIST_HANDLER *sendit, void
 VolBytes,LastWritten,VolRetention,Recycle \
 FROM Media WHERE Media.PoolId=%d ORDER BY MediaId", mdbr->PoolId);
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
 
    list_result(mdb, sendit, ctx);
    
    sql_free_result(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
 }
 
 void db_list_jobmedia_records(B_DB *mdb, uint32_t JobId, DB_LIST_HANDLER *sendit, void *ctx)
@@ -120,16 +120,16 @@ FROM JobMedia, Media WHERE Media.MediaId=JobMedia.MediaId and JobMedia.JobId=%d"
 FROM JobMedia, Media WHERE Media.MediaId=JobMedia.MediaId");
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
 
    list_result(mdb, sendit, ctx);
    
    sql_free_result(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
 }
 
 
@@ -152,16 +152,16 @@ JobFiles,JobBytes,JobStatus FROM Job");
 JobFiles,JobBytes,JobStatus FROM Job WHERE Job.JobId=%d", jr->JobId);
    }
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
 
    list_result(mdb, sendit, ctx);
    
    sql_free_result(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
 }
 
 /*
@@ -173,14 +173,14 @@ db_list_job_totals(B_DB *mdb, JOB_DBR *jr, DB_LIST_HANDLER *sendit, void *ctx)
 {
 
 
-   P(mdb->mutex);
+   db_lock(mdb);
 
    /* List by Job */
    Mmsg(&mdb->cmd, "SELECT  count(*) AS Jobs, sum(JobFiles) \
 AS Files, sum(JobBytes) AS Bytes, Name AS Job FROM Job GROUP BY Name");
 
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
 
@@ -193,14 +193,14 @@ AS Files, sum(JobBytes) AS Bytes, Name AS Job FROM Job GROUP BY Name");
 AS Files,sum(JobBytes) As Bytes FROM Job");
 
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
 
    list_result(mdb, sendit, ctx);
    
    sql_free_result(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
 }
 
 
@@ -213,16 +213,16 @@ Filename,Path WHERE File.JobId=%d and Filename.FilenameId=File.FilenameId \
 and Path.PathId=File.PathId",
       jobid);
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (!QUERY_DB(mdb, mdb->cmd)) {
-      V(mdb->mutex);
+      db_unlock(mdb);
       return;
    }
 
    list_result(mdb, sendit, ctx);
    
    sql_free_result(mdb);
-   V(mdb->mutex);
+   db_unlock(mdb);
 }
 
 
index d84eeab77cf8b217999bf371b60a523dcab28e50..5c646f0ea89ac45538c8a236e5a4442125a17642 100644 (file)
@@ -26,8 +26,6 @@
 
  */
 
-/* *****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.
  */
 extern void print_result(B_DB *mdb);
 extern int UpdateDB(char *file, int line, B_DB *db, char *update_cmd);
 
-static int do_update(B_DB *mdb, char *cmd)
-{
-   int stat;
-
-   stat = UPDATE_DB(mdb, cmd);
-   return stat;
-}
-
 /* -----------------------------------------------------------------------
  *
  *   Generic Routines (or almost generic)
@@ -69,10 +59,10 @@ db_add_MD5_to_file_record(B_DB *mdb, FileId_t FileId, char *MD5)
 {
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "UPDATE File SET MD5=\"%s\" WHERE FileId=%d", MD5, FileId);
    stat = UPDATE_DB(mdb, mdb->cmd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -83,10 +73,10 @@ int db_mark_file_record(B_DB *mdb, FileId_t FileId, int JobId)
 {
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "UPDATE File SET FileIndex=%d WHERE FileId=%d", JobId, FileId);
    stat = UPDATE_DB(mdb, mdb->cmd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -111,12 +101,12 @@ db_update_job_start_record(B_DB *mdb, JOB_DBR *jr)
    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
    JobTDate = (btime_t)stime;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd, "UPDATE Job SET Level='%c', StartTime=\"%s\", \
 ClientId=%d, JobTDate=%s WHERE JobId=%d",
       (char)(jr->Level), dt, jr->ClientId, edit_uint64(JobTDate, ed1), jr->JobId);
    stat = UPDATE_DB(mdb, mdb->cmd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -143,7 +133,7 @@ db_update_job_end_record(B_DB *mdb, JOB_DBR *jr)
    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
    JobTDate = ttime;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd,
       "UPDATE Job SET JobStatus='%c', EndTime='%s', \
 ClientId=%d, JobBytes=%s, JobFiles=%d, JobErrors=%d, VolSessionId=%d, \
@@ -153,7 +143,7 @@ VolSessionTime=%d, PoolId=%d, FileSetId=%d, JobTDate=%s WHERE JobId=%d",
       jr->PoolId, jr->FileSetId, edit_uint64(JobTDate, ed2), jr->JobId);
 
    stat = UPDATE_DB(mdb, mdb->cmd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -163,7 +153,7 @@ db_update_pool_record(B_DB *mdb, POOL_DBR *pr)
 {
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    Mmsg(&mdb->cmd,
 "UPDATE Pool SET NumVols=%d, MaxVols=%d, UseOnce=%d, UseCatalog=%d, \
 AcceptAnyVolume=%d, LabelFormat=\"%s\" WHERE PoolId=%d",
@@ -171,7 +161,7 @@ AcceptAnyVolume=%d, LabelFormat=\"%s\" WHERE PoolId=%d",
       pr->AcceptAnyVolume, pr->LabelFormat, pr->PoolId);
 
    stat = UPDATE_DB(mdb, mdb->cmd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
@@ -195,14 +185,11 @@ db_update_media_record(B_DB *mdb, MEDIA_DBR *mr)
    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
 
    Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
-   P(mdb->mutex);
+   db_lock(mdb);
    if (mr->VolMounts == 1) {
       Mmsg(&mdb->cmd, "UPDATE Media SET FirstWritten=\"%s\"\
  WHERE VolumeName=\"%s\"", dt, mr->VolumeName);
-      if (do_update(mdb, mdb->cmd) == 0) {
-        V(mdb->mutex);
-        return 0;
-      }
+      UPDATE_DB(mdb, mdb->cmd);
    }
 
    Mmsg(&mdb->cmd, "UPDATE Media SET VolJobs=%d,\
@@ -215,7 +202,7 @@ db_update_media_record(B_DB *mdb, MEDIA_DBR *mr)
    mr->VolStatus, mr->VolumeName);
 
    stat = UPDATE_DB(mdb, mdb->cmd);
-   V(mdb->mutex);
+   db_unlock(mdb);
    return stat;
 }
 
index e687da4b788528ebf012fc89cde84d32f034dacb..b9a33905c518de4e490b141fe18ce37410b537d9 100644 (file)
@@ -78,9 +78,9 @@ db_init_database(char *db_name, char *db_user, char *db_password)
    memset(mdb, 0, sizeof(B_DB));
    mdb->db_name = bstrdup(db_name);
    mdb->have_insert_id = TRUE; 
-   mdb->errmsg = (char *) get_pool_memory(PM_EMSG); /* get error message buffer */
+   mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */
    *mdb->errmsg = 0;
-   mdb->cmd = (char *) get_pool_memory(PM_EMSG);    /* get command buffer */
+   mdb->cmd = get_pool_memory(PM_EMSG);    /* get command buffer */
    mdb->ref_count = 1;
    qinsert(&db_list, &mdb->bq);           /* put db in list */
    V(mutex);
@@ -104,11 +104,19 @@ db_open_database(B_DB *mdb)
       return 1;
    }
    mdb->connected = FALSE;
+#ifdef needed
    if (pthread_mutex_init(&mdb->mutex, NULL) != 0) {
       Mmsg1(&mdb->errmsg, _("Unable to initialize DB mutex. ERR=%s\n"), strerror(errno));
       V(mutex);
       return 0;
    }
+#endif
+
+   if (rwl_init(&mdb->lock) != 0) {
+      Mmsg1(&mdb->errmsg, "Unable to initialize DB lock. ERR=%s\n", strerror(errno));
+      V(mutex);
+      return 0;
+   }
 
    /* open the database */
    len = strlen(working_directory) + strlen(mdb->db_name) + 5; 
@@ -159,7 +167,8 @@ db_close_database(B_DB *mdb)
       if (mdb->connected && mdb->db) {
         sqlite_close(mdb->db);
       }
-      pthread_mutex_destroy(&mdb->mutex);
+/*    pthread_mutex_destroy(&mdb->mutex); */
+      rwl_destroy(&mdb->lock);      
       free_pool_memory(mdb->errmsg);
       free_pool_memory(mdb->cmd);
       if (mdb->db_name) {
@@ -273,7 +282,7 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void
    struct rh_data rh_data;
    int stat;
 
-   P(mdb->mutex);
+   db_lock(mdb);
    if (mdb->sqlite_errmsg) {
       actuallyfree(mdb->sqlite_errmsg);
       mdb->sqlite_errmsg = NULL;
@@ -283,10 +292,10 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void
    stat = sqlite_exec(mdb->db, query, sqlite_result, (void *)&rh_data, &mdb->sqlite_errmsg);
    if (stat != 0) {
       Mmsg(&mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb));
-      V(mdb->mutex);
+      db_unlock(mdb);
       return 0;
    }
-   V(mdb->mutex);
+   db_unlock(mdb);
    return 1;
 }
 
index fd0c0d1c04541eb0950c9d7a220aedf651a3c814..0bbf313a1d1e8254c568d7a9f0f0d21485e0839a 100644 (file)
@@ -23,7 +23,7 @@ dummy:
 
 #
 SVRSRCS = dird.c authenticate.c autoprune.c \
-         backup.c \
+         autorecycle.c backup.c \
          catreq.c dird_conf.c \
          fd_cmds.c getmsg.c job.c \
          mountreq.c msgchan.c newvol.c \
@@ -36,7 +36,7 @@ SVRSRCS = dird.c authenticate.c autoprune.c \
          ua_select.c ua_server.c \
          ua_status.c verify.c
 SVROBJS = dird.o authenticate.o autoprune.o \
-         backup.o \
+         autorecycle.o backup.o \
          catreq.o dird_conf.o \
          fd_cmds.o getmsg.o job.o \
          mountreq.o msgchan.o newvol.o \
diff --git a/bacula/src/dird/autoprune.c b/bacula/src/dird/autoprune.c
new file mode 100644 (file)
index 0000000..a925a95
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ *
+ *   Bacula Director -- Automatic Pruning 
+ *     Applies retention periods
+ *
+ *     Kern Sibbald, May MMII
+ *
+ *   Version $Id$
+ */
+
+/*
+   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 */
+
+void create_ua_context(JCR *jcr, UAContext *ua)
+{
+   memset(ua, 0, sizeof(UAContext));
+   ua->jcr = jcr;
+   ua->db = jcr->db;
+   ua->cmd = get_pool_memory(PM_FNAME);
+   ua->args = get_pool_memory(PM_FNAME);
+   ua->verbose = 1;
+}
+
+void free_ua_context(UAContext *ua)
+{
+   if (ua->cmd) {
+      free_pool_memory(ua->cmd);
+   }
+   if (ua->args) {
+      free_pool_memory(ua->args);
+   }
+}
+
+/*
+ * Auto Prune Jobs and Files
+ *   Volumes are done separately
+ */
+int do_autoprune(JCR *jcr)
+{
+   UAContext ua;
+   CLIENT *client;
+   int pruned;
+
+   if (!jcr->client) {               /* temp -- remove me */
+      return 1;
+   }
+
+   create_ua_context(jcr, &ua);
+
+   client = jcr->client;
+
+   if (jcr->job->PruneJobs || jcr->client->AutoPrune) {
+      Jmsg(jcr, M_INFO, 0, _("Begin pruning Jobs.\n"));
+      prune_jobs(&ua, client);
+      pruned = TRUE;
+   } else {
+      pruned = FALSE;
+   }
+  
+   if (jcr->job->PruneFiles || jcr->client->AutoPrune) {
+      Jmsg(jcr, M_INFO, 0, _("Begin pruning Files.\n"));
+      prune_files(&ua, client);
+      pruned = TRUE;
+   }
+   if (pruned) {
+      Jmsg(jcr, M_INFO, 0, _("End auto prune.\n\n"));
+   }
+
+   free_ua_context(&ua);
+   return 1;   
+}
+
+/*
+ * Prune all volumes in current Pool.
+ *
+ *  Return 0: on error
+ *        number of Volumes Purged
+ */
+int prune_volumes(JCR *jcr)
+{
+   int stat = 0;
+   int i;
+   uint32_t *ids = NULL;
+   int num_ids = 0;
+   MEDIA_DBR mr;
+   POOL_DBR pr;
+   UAContext ua;
+
+   if (!jcr->job->PruneVolumes && !jcr->pool->AutoPrune) {
+      Dmsg0(200, "AutoPrune not set in Pool.\n");
+      return stat;
+   }
+   memset(&mr, 0, sizeof(mr));
+   memset(&pr, 0, sizeof(pr));
+   create_ua_context(jcr, &ua);
+
+   db_lock(jcr->db);
+
+   pr.PoolId = jcr->PoolId;
+   if (!db_get_pool_record(jcr->db, &pr) || !db_get_media_ids(jcr->db, &num_ids, &ids)) {
+      Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
+      goto rtn;
+   }
+
+
+   for (i=0; i<num_ids; i++) {
+      mr.MediaId = ids[i];
+      if (!db_get_media_record(jcr->db, &mr)) {
+         Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
+        continue;
+      }
+      /* Prune only Volumes from current Pool */
+      if (pr.PoolId != mr.PoolId) {
+        continue;
+      }
+      /* Prune only Volumes with status "Full" */
+      if (strcmp(mr.VolStatus, "Full") != 0) {
+        continue;
+      }
+      Dmsg1(200, "Prune Volume %s\n", mr.VolumeName);
+      stat += prune_volume(&ua, &pr, &mr); 
+      Dmsg1(200, "Num pruned = %d\n", stat);
+   }   
+rtn:
+   db_unlock(jcr->db);
+   free_ua_context(&ua);
+   if (ids) {
+      free(ids);
+   }
+   return stat;
+}
index 386f82669847d1e5db88650a3d90ddf5abb7cda0..3c726a49d66db7480bd556b5fe7cbbfbf72c9e03 100644 (file)
@@ -358,7 +358,8 @@ static void backup_cleanup(JCR *jcr, int TermCode, char *since)
       case JS_Terminated:
          term_msg = _("Backup OK");
         break;
-      case JS_Errored:
+      case JS_FatalError:
+      case JS_ErrorTerminated:
          term_msg = _("*** Backup Error ***"); 
         msg_type = M_ERROR;          /* Generate error message */
         if (jcr->store_bsock) {
index de26079d7f1dfd8c400c68ec11f83a9c1cd68bcb..58bef7f4dbdbd69daee46250e4d006758f2e78ab 100644 (file)
@@ -92,15 +92,15 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
         ok = TRUE;
       } else {
         /* Well, try finding recycled tapes */
-         strcpy(mr.VolStatus, "Recycle");
-        if (db_find_next_volume(jcr->db, index, &mr)) {
-           jcr->MediaId = mr.MediaId;
-            Dmsg1(20, "Find_next_vol MediaId=%d\n", jcr->MediaId);
-           strcpy(jcr->VolumeName, mr.VolumeName);
-           ok = TRUE;
-        } else {
-           /* See if we can create a new Volume */
-           ok = newVolume(jcr);
+        ok = find_recycled_volume(jcr, &mr);
+        if (!ok) {
+           if (prune_volumes(jcr)) {
+              ok = recycle_a_volume(jcr, &mr);
+           }
+           if (!ok) {
+              /* See if we can create a new Volume */
+              ok = newVolume(jcr);
+           }
         }
       }
       /*
@@ -117,7 +117,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
       }
 
    /* 
-    * Request to find specific volume information
+    * Request to find specific Volume information
     */
    } else if (sscanf(bs->msg, Get_Vol_Info, &Job, &mr.VolumeName) == 2) {
       Dmsg1(120, "CatReq GetVolInfo Vol=%s\n", mr.VolumeName);
index 4073fb268042579764797a33ca593b69016a79f4..a0bc675d0a67d6aa4c25674a5e09b00487d25390 100644 (file)
@@ -171,7 +171,10 @@ static struct res_items job_items[] = {
    {"client",   store_res,     ITEM(res_job.client),   R_CLIENT, 0, 0},
    {"fileset",  store_res,     ITEM(res_job.fs),       R_FILESET, 0, 0},
    {"maxruntime", store_time,  ITEM(res_job.MaxRunTime), 0, 0, 0},
-   {"maxstartdelay", store_time, ITEM(res_job.MaxStartDelay), 0, 0, 0},
+   {"maxstartdelay", store_time,ITEM(res_job.MaxStartDelay), 0, 0, 0},
+   {"prunejobs",   store_yesno, ITEM(res_job.PruneJobs), 1, ITEM_DEFAULT, 0},
+   {"prunefiles",  store_yesno, ITEM(res_job.PruneFiles), 1, ITEM_DEFAULT, 0},
+   {"prunevolumes", store_yesno, ITEM(res_job.PruneVolumes), 1, ITEM_DEFAULT, 0},
    {NULL, NULL, NULL, 0, 0, 0} 
 };
 
@@ -276,6 +279,7 @@ struct s_jl joblevels[] = {
  */
 struct s_jt jobtypes[] = {
    {"backup",        JT_BACKUP},
+   {"admin",         JT_ADMIN},
    {"verify",        JT_VERIFY},
    {"restore",       JT_RESTORE},
    {NULL,           0}
index eebc692dfd47cd089bcffe2bb70f289ad4dbd47d..94a1e05038915c46125f5cc2ff8e6bf7bba944ce 100644 (file)
 /*
  * Resource codes -- they must be sequential for indexing   
  */
-#define R_FIRST                       1001
+#define R_FIRST                      1001
 
-#define R_DIRECTOR                    1001
-#define R_CLIENT                      1002
-#define R_JOB                         1003
-#define R_STORAGE                     1004
-#define R_CATALOG                     1005
-#define R_SCHEDULE                    1006
-#define R_FILESET                     1007
-#define R_GROUP                       1008
-#define R_POOL                        1009
-#define R_MSGS                        1010
+#define R_DIRECTOR                   1001
+#define R_CLIENT                     1002
+#define R_JOB                        1003
+#define R_STORAGE                    1004
+#define R_CATALOG                    1005
+#define R_SCHEDULE                   1006
+#define R_FILESET                    1007
+#define R_GROUP                      1008
+#define R_POOL                       1009
+#define R_MSGS                       1010
 
-#define R_LAST                        R_MSGS
+#define R_LAST                       R_MSGS
 
 /*
  * Some resource attributes
  */
-#define R_NAME                        1020
-#define R_ADDRESS                     1021
-#define R_PASSWORD                    1022
-#define R_TYPE                        1023
-#define R_BACKUP                      1024
+#define R_NAME                       1020
+#define R_ADDRESS                    1021
+#define R_PASSWORD                   1022
+#define R_TYPE                       1023
+#define R_BACKUP                     1024
 
 
 /* Used for certain KeyWord tables */
-struct s_kw {       
+struct s_kw {      
    char *name;
-   int token;   
+   int token;  
 };
 
 /* Job Level keyword structure */
 struct s_jl {
-   char *level_name;                  /* level keyword */
-   int  level;                        /* level */
-   int  job_type;                     /* JobType permitting this level */
+   char *level_name;                 /* level keyword */
+   int level;                        /* level */
+   int job_type;                     /* JobType permitting this level */
 };
 
 /* Job Type keyword structure */
@@ -77,21 +77,21 @@ struct s_jt {
 /* Definition of the contents of each Resource */
 
 /* 
- *   Director Resource  
+ *   Director Resource 
  *
  */
 struct s_res_dir {
-   RES   hdr;
-   int   DIRport;                     /* where we listen -- UA port server port */
-   char *password;                    /* Password for UA access */
-   char *query_file;                  /* SQL query file */
-   char *working_directory;           /* WorkingDirectory */
-   char *pid_directory;               /* PidDirectory */
-   char *subsys_directory;            /* SubsysDirectory */
+   RES  hdr;
+   int  DIRport;                     /* where we listen -- UA port server port */
+   char *password;                   /* Password for UA access */
+   char *query_file;                 /* SQL query file */
+   char *working_directory;          /* WorkingDirectory */
+   char *pid_directory;              /* PidDirectory */
+   char *subsys_directory;           /* SubsysDirectory */
    struct s_res_msgs *messages;       /* Daemon message handler */
-   int   MaxConcurrentJobs;
-   btime_t FDConnectTimeout;          /* timeout for connect in seconds */
-   btime_t SDConnectTimeout;          /* timeout in seconds */
+   int  MaxConcurrentJobs;
+   btime_t FDConnectTimeout;         /* timeout for connect in seconds */
+   btime_t SDConnectTimeout;         /* timeout in seconds */
 };
 typedef struct s_res_dir DIRRES;
 
@@ -100,12 +100,12 @@ typedef struct s_res_dir DIRRES;
  *
  */
 struct s_res_client {
-   RES   hdr;
+   RES  hdr;
 
-   int   FDport;                      /* Where File daemon listens */
-   int   AutoPrune;                   /* Do automatic pruning? */
-   btime_t FileRetention;             /* file retention period in seconds */
-   btime_t JobRetention;              /* job retention period in seconds */
+   int  FDport;                      /* Where File daemon listens */
+   int  AutoPrune;                   /* Do automatic pruning? */
+   btime_t FileRetention;            /* file retention period in seconds */
+   btime_t JobRetention;             /* job retention period in seconds */
    char *address;
    char *password;
    struct s_res_cat    *catalog;       /* Catalog resource */
@@ -117,10 +117,10 @@ typedef struct s_res_client CLIENT;
  * 
  */
 struct s_res_store {
-   RES   hdr;
+   RES  hdr;
 
-   int   SDport;                      /* port where Directors connect */
-   int   SDDport;                     /* data port for File daemon */
+   int  SDport;                      /* port where Directors connect */
+   int  SDDport;                     /* data port for File daemon */
    char *address;
    char *password;
    char *media_type;
@@ -133,9 +133,9 @@ typedef struct s_res_store STORE;
  *
  */
 struct s_res_cat {
-   RES   hdr;
+   RES  hdr;
 
-   int   DBport;                      /* Port -- not yet implemented */
+   int  DBport;                      /* Port -- not yet implemented */
    char *address;
    char *db_password;
    char *db_user;
@@ -148,22 +148,25 @@ typedef struct s_res_cat CAT;
  *
  */
 struct s_res_job {
-   RES   hdr;
-
-   int   JobType;                     /* job type (backup, verify, restore */
-   int   level;                       /* default backup/verify level */
-   int   RestoreJobId;                /* What -- JobId to restore */
-   char *RestoreWhere;                /* Where on disk to restore -- directory */
-   int   RestoreOptions;              /* How (overwrite, ..) */
-   btime_t MaxRunTime;                /* max run time in seconds */
-   btime_t MaxStartDelay;             /* max start delay in seconds */
+   RES  hdr;
+
+   int  JobType;                     /* job type (backup, verify, restore */
+   int  level;                       /* default backup/verify level */
+   int  RestoreJobId;                /* What -- JobId to restore */
+   char *RestoreWhere;               /* Where on disk to restore -- directory */
+   int  RestoreOptions;              /* How (overwrite, ..) */
+   btime_t MaxRunTime;               /* max run time in seconds */
+   btime_t MaxStartDelay;            /* max start delay in seconds */
+   int PruneJobs;                    /* Force pruning of Jobs */
+   int PruneFiles;                   /* Force pruning of Files */
+   int PruneVolumes;                 /* Force pruning of Volumes */
 
    struct s_res_msgs   *messages;     /* How and where to send messages */
    struct s_res_sch    *schedule;     /* When -- Automatic schedule */
    struct s_res_client *client;       /* Who to backup */
-   struct s_res_fs     *fs;           /* What to backup -- Fileset */
+   struct s_res_fs     *fs;          /* What to backup -- Fileset */
    struct s_res_store  *storage;      /* Where is device -- Storage daemon */
-   struct s_res_pool   *pool;         /* Where is media -- Media Pool */
+   struct s_res_pool   *pool;        /* Where is media -- Media Pool */
 };
 typedef struct s_res_job JOB;
 
@@ -172,7 +175,7 @@ typedef struct s_res_job JOB;
  *
  */
 struct s_res_fs {
-   RES   hdr;
+   RES  hdr;
 
    char **include_array;
    int num_includes;
@@ -180,8 +183,8 @@ struct s_res_fs {
    char **exclude_array;
    int num_excludes;
    int exclude_size;
-   int have_MD5;                      /* set if MD5 initialized */
-   struct MD5Context md5c;            /* MD5 of include/exclude */
+   int have_MD5;                     /* set if MD5 initialized */
+   struct MD5Context md5c;           /* MD5 of include/exclude */
 };
 typedef struct s_res_fs FILESET;
  
@@ -191,7 +194,7 @@ typedef struct s_res_fs FILESET;
  *
  */
 struct s_res_sch {
-   RES   hdr;
+   RES  hdr;
 
    struct s_run *run;
 };
@@ -202,7 +205,7 @@ typedef struct s_res_sch SCHED;
  *
  */
 struct s_res_group {
-   RES   hdr;
+   RES  hdr;
 };
 typedef struct s_res_group GROUP;
 
@@ -211,18 +214,18 @@ typedef struct s_res_group GROUP;
  *
  */
 struct s_res_pool {
-   RES   hdr;
+   RES  hdr;
 
    char *pool_type;
-   char *label_format;                /* Label format string */
-   int   use_catalog;                 /* maintain catalog for media */
-   int   catalog_files;               /* maintain file entries in catalog */
-   int   use_volume_once;             /* write on volume only once */
-   int   accept_any_volume;           /* accept any volume */
-   int   max_volumes;                 /* max number of volumes */
-   btime_t VolRetention;              /* volume retention period in seconds */
-   int   AutoPrune;                   /* default for pool auto prune */
-   int   Recycle;                     /* default for media recycle yes/no */
+   char *label_format;               /* Label format string */
+   int  use_catalog;                 /* maintain catalog for media */
+   int  catalog_files;               /* maintain file entries in catalog */
+   int  use_volume_once;             /* write on volume only once */
+   int  accept_any_volume;           /* accept any volume */
+   int  max_volumes;                 /* max number of volumes */
+   btime_t VolRetention;             /* volume retention period in seconds */
+   int  AutoPrune;                   /* default for pool auto prune */
+   int  Recycle;                     /* default for media recycle yes/no */
 };
 typedef struct s_res_pool POOL;
 
@@ -231,16 +234,16 @@ typedef struct s_res_pool POOL;
  * resource structure definitions.
  */
 union u_res {
-   struct s_res_dir     res_dir;
-   struct s_res_client  res_client;
-   struct s_res_store   res_store;
-   struct s_res_cat     res_cat;
-   struct s_res_job     res_job;
-   struct s_res_fs      res_fs;
-   struct s_res_sch     res_sch;
-   struct s_res_group   res_group;
-   struct s_res_pool    res_pool;
-   struct s_res_msgs    res_msgs;
+   struct s_res_dir    res_dir;
+   struct s_res_client res_client;
+   struct s_res_store  res_store;
+   struct s_res_cat    res_cat;
+   struct s_res_job    res_job;
+   struct s_res_fs     res_fs;
+   struct s_res_sch    res_sch;
+   struct s_res_group  res_group;
+   struct s_res_pool   res_pool;
+   struct s_res_msgs   res_msgs;
    RES hdr;
 };
 
@@ -249,17 +252,17 @@ typedef union u_res URES;
 
 /* Run structure contained in Schedule Resource */
 struct s_run {
-   struct s_run *next;                /* points to next run record */
-   int level;                         /* level override */
+   struct s_run *next;               /* points to next run record */
+   int level;                        /* level override */
    int job_type;  
-   POOL *pool;                        /* Pool override */
-   STORE *storage;                    /* Storage override */
-   MSGS *msgs;                        /* Messages override */
+   POOL *pool;                       /* Pool override */
+   STORE *storage;                   /* Storage override */
+   MSGS *msgs;                       /* Messages override */
    char *since;
    int level_no;
-   int minute;                        /* minute to run job */
-   time_t last_run;                   /* last time run */
-   time_t next_run;                   /* next time to run */
+   int minute;                       /* minute to run job */
+   time_t last_run;                  /* last time run */
+   time_t next_run;                  /* next time to run */
    char hour[nbytes_for_bits(24)];    /* bit set for each hour */
    char mday[nbytes_for_bits(31)];    /* bit set for each day of month */
    char month[nbytes_for_bits(12)];   /* bit set for each month */
index 8496d1caacfd03b2bdc12a9f0bdbf6a0d79d0730..9f612b24e871f180db1e72c77057834a33df085e 100644 (file)
@@ -30,6 +30,11 @@ extern int authenticate_user_agent(BSOCK *ua);
 
 /* autoprune.c */
 extern int do_autoprune(JCR *jcr);
+int prune_volumes(JCR *jcr);
+
+/* autorecycle.c */
+int recycle_a_volume(JCR *jcr, MEDIA_DBR *mr);
+int find_recycled_volume(JCR *jcr, MEDIA_DBR *mr);
 
 
 /* catreq.c */
index c6e32556b5e2628b2328a8ae46d6dcd93c3b98e4..3f94de08fdde537715d1d6e74f9838b6356c45bf 100644 (file)
@@ -268,20 +268,25 @@ int prunecmd(UAContext *ua, char *cmd)
  * 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.
+ *
+ * This routine assumes you want the pruning to be done. All checking
+ *  must be done before calling this routine.
  */
 int prune_files(UAContext *ua, CLIENT *client)
 {
    struct s_file_del_ctx del;
-   char *query = (char *)get_pool_memory(PM_MESSAGE);
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
    int i;
    btime_t now, period;
    CLIENT_DBR cr;
    char ed1[50], ed2[50];
 
+   db_lock(ua->db);
    memset(&cr, 0, sizeof(cr));
    memset(&del, 0, sizeof(del));
    strcpy(cr.Name, client->hdr.name);
    if (!db_create_client_record(ua->db, &cr)) {
+      db_unlock(ua->db);
       return 0;
    }
 
@@ -344,6 +349,7 @@ int prune_files(UAContext *ua, CLIENT *client)
       ed1, ed2, client->hdr.name, client->catalog->hdr.name);
    
 bail_out:
+   db_unlock(ua->db);
    if (del.JobId) {
       free(del.JobId);
    }
@@ -394,10 +400,12 @@ int prune_jobs(UAContext *ua, CLIENT *client)
    CLIENT_DBR cr;
    char ed1[50];
 
+   db_lock(ua->db);
    memset(&cr, 0, sizeof(cr));
    memset(&del, 0, sizeof(del));
    strcpy(cr.Name, client->hdr.name);
    if (!db_create_client_record(ua->db, &cr)) {
+      db_unlock(ua->db);
       return 0;
    }
 
@@ -441,7 +449,7 @@ int prune_jobs(UAContext *ua, CLIENT *client)
       
    if (cnt.count == 0) {
       if (ua->verbose) {
-         bsendmsg(ua, _("No Jobs for client %s found to prune from %s catalog.\n"),
+         bsendmsg(ua, _("No Jobs found for client %s to prune from %s catalog.\n"),
            client->hdr.name, client->catalog->hdr.name);
       }
       goto bail_out;
@@ -484,6 +492,7 @@ int prune_jobs(UAContext *ua, CLIENT *client)
    
 bail_out:
    drop_temp_tables(ua);
+   db_unlock(ua->db);
    if (del.JobId) {
       free(del.JobId);
    }
@@ -495,17 +504,18 @@ bail_out:
 }
 
 /*
- * Prune volumes
+ * Prune a given Volume
  */
 int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
 {
    char *query = (char *)get_pool_memory(PM_MESSAGE);
    struct s_count_ctx cnt;
    struct s_file_del_ctx del;
-   int i;
+   int i, stat = 0;
    JOB_DBR jr;
    btime_t now, period;
 
+   db_lock(ua->db);
    memset(&jr, 0, sizeof(jr));
    memset(&del, 0, sizeof(del));
    cnt.count = 0;
@@ -513,7 +523,7 @@ int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
    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;
+      goto rtn;
    }
       
    if (cnt.count == 0) {
@@ -521,10 +531,8 @@ int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
          bsendmsg(ua, "There are no Jobs associated with Volume %s. It is purged.\n",
            mr->VolumeName);
       }
-      if (!mark_media_purged(ua, mr)) {
-        goto bail_out;
-      }
-      goto bail_out;
+      stat = mark_media_purged(ua, mr);
+      goto rtn;
    }
 
    if (cnt.count < MAX_DEL_LIST_LEN) {
@@ -535,28 +543,32 @@ int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
 
    del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
 
+   /* ***FIXME*** could make this do JobTDate check too */
    Mmsg(&query, "SELECT JobId FROM JobMedia WHERE MediaId=%d", mr->MediaId);
    if (!db_sql_query(ua->db, query, file_delete_handler, (void *)&del)) {
       if (ua->verbose) {
          bsendmsg(ua, "%s", db_strerror(ua->db));
       }
       Dmsg0(050, "Count failed\n");
-      goto bail_out;
+      goto rtn;
    }
 
-   /* Use Volume Retention to purge Jobs and Files */
+   /* Use Volume Retention to prune Jobs and Files */
    period = mr->VolRetention;
    now = (btime_t)time(NULL);
 
+   Dmsg3(200, "Now=%d period=%d now-period=%d\n", (int)now, (int)period,
+      (int)(now-period));
    for (i=0; i < del.num_ids; i++) {
       jr.JobId = del.JobId[i];
       if (!db_get_job_record(ua->db, &jr)) {
         continue;
       }
+      Dmsg2(200, "Looking at %s JobTdate=%d\n", jr.Job, (int)jr.JobTDate);
       if (jr.JobTDate >= (now - period)) {
         continue;
       }
-      Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+      Dmsg2(200, "Delete JobId=%d Job=%s\n", del.JobId[i], jr.Job);
       Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
       db_sql_query(ua->db, query, NULL, (void *)NULL);
       Mmsg(&query, "DELETE FROM Job WHERE JobId=%d", del.JobId[i]);
@@ -569,17 +581,21 @@ int prune_volume(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
    if (del.JobId) {
       free(del.JobId);
    }
-   bsendmsg(ua, _("Pruned %d Jobs on Volume %s from catalog.\n"), del.num_del,
-      mr->VolumeName);
+   if (ua->verbose) {
+      bsendmsg(ua, _("Pruned %d Jobs on Volume %s from catalog.\n"), del.num_del,
+        mr->VolumeName);
+   }
 
    /* If purged, mark it so */
    if (del.num_ids == del.num_del) {
-      mark_media_purged(ua, mr);
+      Dmsg0(200, "Volume is purged.\n");
+      stat = mark_media_purged(ua, mr);
    }
 
-bail_out:   
+rtn:
+   db_unlock(ua->db);
    free_pool_memory(query);
-   return 1;
+   return stat;
 }
 
 static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr)
@@ -593,6 +609,7 @@ static int mark_media_purged(UAContext *ua, MEDIA_DBR *mr)
         }
         return 0;
       }
+      return 1;
    }
-   return 1;
+   return strcpy(mr->VolStatus, "Purged") == 0;
 }
index 2134be18d2e5e92cd68f3637f75832c8b37cada8..8287baa50ffb3ffa21a345b5d2eb31cb53a11313 100644 (file)
@@ -168,7 +168,7 @@ int do_verify(JCR *jcr)
          level = "data";
         break;
       default:
-         Emsg1(M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->level);
+         Jmsg1(jcr, M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->level);
         verify_cleanup(jcr, JS_ErrorTerminated);                    
         return 0;
    }
@@ -204,7 +204,7 @@ int do_verify(JCR *jcr)
       get_attributes_and_put_in_catalog(jcr);
 
    } else {
-      Emsg1(M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->level);
+      Jmsg1(jcr, M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->level);
       verify_cleanup(jcr, JS_ErrorTerminated);                   
       return 0;
    }
index 78fdf569383ddaf7f23a96b46b62b6075a22a8aa..48264b2dfa423177245dd277d24012489eda0fef 100644 (file)
@@ -57,8 +57,9 @@
 #define JS_Running               'R'
 #define JS_Blocked               'B'
 #define JS_Terminated            'T'  /* terminated normally */
-#define JS_ErrorTerminated       'E'
-#define JS_Errored               'E'
+#define JS_ErrorTerminated       'E'  /* Job terminated in error */
+#define JS_Error                 'e'  /* Non-fatal error */
+#define JS_FatalError            'f'  /* Fatal error */
 #define JS_Differences           'D'  /* Verify differences */
 #define JS_Cancelled             'A'  /* cancelled by user */
 #define JS_WaitFD                'F'  /* waiting on File daemon */
@@ -83,16 +84,16 @@ struct s_jcr {
    BSOCK *file_bsock;                 /* File daemon connection socket */
    JCR_free_HANDLER *daemon_free_jcr; /* Local free routine */
    int use_count;                     /* use count */
-   char *errmsg;                      /* edited error message */
+   POOLMEM *errmsg;                   /* edited error message */
    char Job[MAX_NAME_LENGTH];         /* Job name */
    uint32_t JobId;                    /* Director's JobId */
    uint32_t VolSessionId;
    uint32_t VolSessionTime;
    uint32_t JobFiles;                 /* Number of files written, this job */
-   uint32_t JobErrors;
+   uint32_t JobErrors;                /* */
    uint64_t JobBytes;                 /* Number of bytes processed this job */
+   uint32_t Errors;                   /* Number of non-fatal errors */
    int JobStatus;                     /* ready, running, blocked, terminated */ 
-   int JobTermCode;                   /* termination code */
    int JobType;                       /* backup, restore, verify ... */
    int level;
    int authenticated;                 /* set when client authenticated */
index 01d96d83768a781a55369c75bd63f1a2fb5c740c..3e55a917b19f022848326ae71e43962d2c8105ef 100644 (file)
@@ -97,8 +97,14 @@ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
          && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
 
 smtp:  smtp.o
-       $(CXX) $(LDFLAGS) -L. -o $@ smtp.o  \
-             $(LIBS) $(DLIB) -lbac -lm
+       $(CXX) $(LDFLAGS) -L. -o $@ smtp.o $(LIBS) $(DLIB) -lbac -lm
+
+rwlock_test:  rwlock.o
+       rm -f rwlock.o
+       $(CXX) -DTEST_RWLOCK $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(GMP_INC) $(CFLAGS) rwlock.c
+       $(CXX) $(LDFLAGS) -L. -o $@ rwlock.o $(LIBS) $(DLIB) -lbac -lm
+       rm -f rwlock.o
+       $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(GMP_INC) $(CFLAGS) rwlock.c
         
 install:
        $(INSTALL_PROGRAM) smtp $(DESTDIR)/$(sbindir)/smtp
@@ -108,7 +114,7 @@ uninstall:
 
 clean:
        $(RMF) *.a core a.out *.o *.bak *.tex *.pdf *~ *.intpro *.extpro 1 2 3
-       $(RMF) smtp
+       $(RMF) smtp rwlock_test
 
 realclean: clean
        $(RMF) tags
index 4991646a3ca2e24ba9850282c5462991a15063ea..34caee427704699543388991a94a710f94ed9f9d 100644 (file)
@@ -151,7 +151,7 @@ bnet_recv(BSOCK *bsock)
 
    /* Make sure the buffer is big enough + one byte for EOS */
    if (pktsiz >= (int32_t)sizeof_pool_memory(bsock->msg)) {
-      bsock->msg = (char *) realloc_pool_memory(bsock->msg, pktsiz + 100);
+      bsock->msg = realloc_pool_memory(bsock->msg, pktsiz + 100);
    }
 
    bsock->timer_start = watchdog_time; /* set start wait time */
@@ -457,7 +457,7 @@ again:
    bs->msglen = bvsnprintf(bs->msg, maxlen, fmt, arg_ptr);
    va_end(arg_ptr);
    if (bs->msglen < 0 || bs->msglen >= maxlen) {
-      bs->msg = (POOLMEM *)realloc_pool_memory(bs->msg, maxlen + 200);
+      bs->msg = realloc_pool_memory(bs->msg, maxlen + 200);
       goto again;
    }
    return bnet_send(bs) < 0 ? 0 : 1;
@@ -481,7 +481,7 @@ int bnet_set_buffer_size(BSOCK *bs, uint32_t size, int rw)
 #endif
 
    dbuf_size = size;
-   if ((bs->msg = (char *) realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
+   if ((bs->msg = realloc_pool_memory(bs->msg, dbuf_size+100)) == NULL) {
       Emsg0(M_FATAL, 0, "Could not malloc 32K BSOCK data buffer\n");
       return 0;
    }
@@ -578,8 +578,8 @@ init_bsock(int sockfd, char *who, char *host, int port)
    memset(bsock, 0, sizeof(BSOCK));
    bsock->fd = sockfd;
    bsock->errors = 0;
-   bsock->msg = (POOLMEM *)get_pool_memory(PM_MESSAGE);
-   bsock->errmsg = (POOLMEM *)get_pool_memory(PM_MESSAGE);
+   bsock->msg = get_pool_memory(PM_MESSAGE);
+   bsock->errmsg = get_pool_memory(PM_MESSAGE);
    bsock->who = bstrdup(who);
    bsock->host = bstrdup(host);
    bsock->port = port;
@@ -599,8 +599,8 @@ dup_bsock(BSOCK *osock)
       Emsg0(M_ABORT, 0, "Out of memory in dup_bsock.\n");
    }
    memcpy(bsock, osock, sizeof(BSOCK));
-   bsock->msg = (POOLMEM *)get_pool_memory(PM_MESSAGE);
-   bsock->errmsg = (POOLMEM *)get_pool_memory(PM_MESSAGE);
+   bsock->msg = get_pool_memory(PM_MESSAGE);
+   bsock->errmsg = get_pool_memory(PM_MESSAGE);
    bsock->duped = TRUE;
    return bsock;
 }
index fd94021147dd9b446a6ee45891af17ecd893efa5..ea3b94bf019c015172d704644ffc1ec04ada04ff 100755 (executable)
@@ -61,9 +61,9 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
    jcr->use_count = 1;
    pthread_mutex_init(&(jcr->mutex), NULL);
    jcr->JobStatus = JS_Created;       /* ready to run */
-   jcr->VolumeName = (char *) get_pool_memory(PM_FNAME);
+   jcr->VolumeName = get_pool_memory(PM_FNAME);
    jcr->VolumeName[0] = 0;
-   jcr->errmsg = (char *) get_pool_memory(PM_MESSAGE);
+   jcr->errmsg = get_pool_memory(PM_MESSAGE);
    jcr->errmsg[0] = 0;
    jobs = jcr;
    V(mutex);
index 600a4c4eb229e7e5c4ef6cdc624940b5689d2700..f6698aeb91b4d8bbb9afb9b72052d0caca24ea87 100644 (file)
@@ -1,5 +1,9 @@
 /* 
- * Library includes for Bacula lib directory
+ *   Library includes for Bacula lib directory
+ *
+ *   This file contains an include for each library file
+ *   that we use within Bacula. bacula.h includes this
+ *   file and thus picks up everything we need in lib.
  *
  *   Version $Id$
  */
@@ -34,6 +38,7 @@
 #include "bsock.h"
 #include "bshm.h"
 #include "workq.h"
+#include "rwlock.h"
 #include "queue.h"
 #include "serial.h"
 #ifndef HAVE_FNMATCH
index 7c911cb7ff30f90b3910806fe3a74615e10cbebe..d2d434d54e0e75b3c9cf1fbefe74b959bdc93022 100755 (executable)
@@ -281,13 +281,13 @@ void rem_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where)
  * Concatenate a string (str) onto a message (msg)
  *  return new message pointer
  */
-static void add_str(char **base, char **msg, char *str)
+static void add_str(POOLMEM **base, char **msg, char *str)
 {
    int len = strlen(str) + 1;
    char *b, *m;
 
    b = *base;
-   *base = (char *) check_pool_memory_size(*base, len);
+   *base = check_pool_memory_size(*base, len);
    m = *base - b + *msg;
    while (*str) {
       *m++ = *str++;
@@ -306,9 +306,13 @@ static char *job_status_to_str(int stat)
    case JS_Terminated:
       str = "OK";
       break;
-   case JS_Errored:
+   case JS_ErrorTerminated:
+   case JS_Error:
       str = "Error";
       break;
+   case JS_FatalError:
+      str = "Fatal Error";
+      break;
    case JS_Cancelled:
       str = "Cancelled";
       break;
@@ -628,7 +632,7 @@ void term_msg()
 /*
  * Handle sending the message to the appropriate place
  */
-void dispatch_message(void *vjcr, int type, int level, char *buf)
+void dispatch_message(void *vjcr, int type, int level, char *msg)
 {
     DEST *d;   
     char cmd[MAXSTRING];
@@ -637,10 +641,10 @@ void dispatch_message(void *vjcr, int type, int level, char *buf)
     int len;
     MSGS *msgs;
 
-    Dmsg2(200, "Enter dispatch_msg type=%d msg=%s\n", type, buf);
+    Dmsg2(200, "Enter dispatch_msg type=%d msg=%s\n", type, msg);
 
     if (type == M_ABORT) {
-       fprintf(stdout, buf);         /* print this here to INSURE that it is printed */
+       fprintf(stdout, msg);         /* print this here to INSURE that it is printed */
     }
 
     /* Now figure out where to send the message */
@@ -655,7 +659,7 @@ void dispatch_message(void *vjcr, int type, int level, char *buf)
        if (bit_is_set(type, d->msg_types)) {
          switch (d->dest_code) {
             case MD_CONSOLE:
-                Dmsg1(200, "CONSOLE for following err: %s\n", buf);
+                Dmsg1(200, "CONSOLE for following err: %s\n", msg);
                if (!con_fd) {
                    con_fd = fopen(con_fname, "a+");
                    Dmsg0(200, "Console file not open.\n");
@@ -667,29 +671,29 @@ void dispatch_message(void *vjcr, int type, int level, char *buf)
                   len = strlen(cmd);
                    cmd[len++] = ' ';
                   fwrite(cmd, len, 1, con_fd);
-                  len = strlen(buf);
-                   if (len > 0 && buf[len-1] != '\n') {
-                      buf[len++] = '\n';
-                     buf[len] = 0;
+                  len = strlen(msg);
+                   if (len > 0 && msg[len-1] != '\n') {
+                      msg[len++] = '\n';
+                     msg[len] = 0;
                   }
-                  fwrite(buf, len, 1, con_fd);
+                  fwrite(msg, len, 1, con_fd);
                   fflush(con_fd);
                   fcntl(fileno(con_fd), F_UNLCK);
                   console_msg_pending = TRUE;
                }
                break;
             case MD_SYSLOG:
-                Dmsg1(200, "SYSLOG for following err: %s\n", buf);
+                Dmsg1(200, "SYSLOG for following err: %s\n", msg);
                /* We really should do an openlog() here */
-               syslog(LOG_DAEMON|LOG_ERR, buf);
+               syslog(LOG_DAEMON|LOG_ERR, msg);
                break;
             case MD_OPERATOR:
-                Dmsg1(200, "OPERATOR for following err: %s\n", buf);
+                Dmsg1(200, "OPERATOR for following err: %s\n", msg);
                mcmd = get_pool_memory(PM_MESSAGE);
                d->fd = open_mail_pipe(jcr, &mcmd, d);
                free_pool_memory(mcmd);
                if (d->fd) {
-                  fputs(buf, d->fd);
+                  fputs(msg, d->fd);
                   /* Messages to the operator go one at a time */
                   pclose(d->fd);
                   d->fd = NULL;
@@ -697,9 +701,9 @@ void dispatch_message(void *vjcr, int type, int level, char *buf)
                break;
             case MD_MAIL:
             case MD_MAIL_ON_ERROR:
-                Dmsg1(200, "MAIL for following err: %s\n", buf);
+                Dmsg1(200, "MAIL for following err: %s\n", msg);
                if (!d->fd) {
-                  char *name  = (char *)get_pool_memory(PM_MESSAGE);
+                  POOLMEM *name  = get_pool_memory(PM_MESSAGE);
                   make_unique_mail_filename(jcr, &name, d);
                    d->fd = fopen(name, "w+");
                   if (!d->fd) {
@@ -709,14 +713,14 @@ void dispatch_message(void *vjcr, int type, int level, char *buf)
                   }
                   d->mail_filename = name;
                }
-               len = strlen(buf);
+               len = strlen(msg);
                if (len > d->max_len) {
                   d->max_len = len;      /* keep max line length */
                }
-               fputs(buf, d->fd);
+               fputs(msg, d->fd);
                break;
             case MD_FILE:
-                Dmsg1(200, "FILE for following err: %s\n", buf);
+                Dmsg1(200, "FILE for following err: %s\n", msg);
                if (!d->fd) {
                    d->fd = fopen(d->where, "w+");
                   if (!d->fd) {
@@ -724,10 +728,10 @@ void dispatch_message(void *vjcr, int type, int level, char *buf)
                      break;
                   }
                }
-               fputs(buf, d->fd);
+               fputs(msg, d->fd);
                break;
             case MD_APPEND:
-                Dmsg1(200, "APPEND for following err: %s\n", buf);
+                Dmsg1(200, "APPEND for following err: %s\n", msg);
                if (!d->fd) {
                    d->fd = fopen(d->where, "a");
                   if (!d->fd) {
@@ -735,26 +739,26 @@ void dispatch_message(void *vjcr, int type, int level, char *buf)
                      break;
                   }
                }
-               fputs(buf, d->fd);
+               fputs(msg, d->fd);
                break;
             case MD_DIRECTOR:
-                Dmsg1(200, "DIRECTOR for following err: %s\n", buf);
+                Dmsg1(200, "DIRECTOR for following err: %s\n", msg);
                if (jcr && jcr->dir_bsock && !jcr->dir_bsock->errors) {
 
                   jcr->dir_bsock->msglen = Mmsg(&(jcr->dir_bsock->msg),
                         "Jmsg Job=%s type=%d level=%d %s", jcr->Job,
-                        type, level, buf) + 1;
+                        type, level, msg) + 1;
                   bnet_send(jcr->dir_bsock);
                }
                break;
             case MD_STDOUT:
-                Dmsg1(200, "STDOUT for following err: %s\n", buf);
+                Dmsg1(200, "STDOUT for following err: %s\n", msg);
                if (type != M_ABORT && type != M_FATAL)  /* already printed */
-                  fprintf(stdout, buf);
+                  fprintf(stdout, msg);
                break;
             case MD_STDERR:
-                Dmsg1(200, "STDERR for following err: %s\n", buf);
-               fprintf(stderr, buf);
+                Dmsg1(200, "STDERR for following err: %s\n", msg);
+               fprintf(stderr, msg);
                break;
             default:
                break;
@@ -879,16 +883,28 @@ Jmsg(void *vjcr, int type, int level, char *fmt,...)
     int i, len;
     JCR *jcr = (JCR *) vjcr;
     int typesave = type;
+    MSGS *msgs;
+    char *job;
 
     
     Dmsg1(200, "Enter Jmsg type=%d\n", type);
 
+    msgs = NULL;
+    if (jcr) {
+       msgs = jcr->msgs;
+       job = jcr->Job;
+    } 
+    if (msgs == NULL) {
+       msgs = daemon_msgs;
+       job = "*None*";
+    }
+
     buf = rbuf;                   /* we are the Director */
     /* 
      * Check if we have a message destination defined. 
      * We always report M_ABORT 
      */
-    if (type != M_ABORT && jcr->msgs && !bit_is_set(type, jcr->msgs->send_msg)) {
+    if (type != M_ABORT && msgs && !bit_is_set(type, msgs->send_msg)) {
        Dmsg1(200, "No bit set for type %d\n", type);
        return;                       /* no destination */
     }
@@ -897,13 +913,19 @@ Jmsg(void *vjcr, int type, int level, char *fmt,...)
           sprintf(buf, "%s ABORTING due to ERROR\n", my_name);
          break;
        case M_FATAL:
-          sprintf(buf, "%s: Job %s Cancelled because: ", my_name, jcr->Job);
+          sprintf(buf, "%s: Job %s Fatal error: ", my_name, job);
+         if (jcr) {
+            jcr->JobStatus = JS_FatalError;
+         }
          break;
        case M_ERROR:
-          sprintf(buf, "%s: Job %s Error: ", my_name, jcr->Job);
+          sprintf(buf, "%s: Job %s Error: ", my_name, job);
+         if (jcr) {
+            jcr->Errors++;
+         }
          break;
        case M_WARNING:
-          sprintf(buf, "%s: Job %s Warning: ", my_name, jcr->Job);
+          sprintf(buf, "%s: Job %s Warning: ", my_name, job);
          break;
        default:
           sprintf(buf, "%s: ", my_name);
@@ -962,20 +984,24 @@ again:
    len = bvsnprintf(*pool_buf, maxlen, fmt, arg_ptr);
    va_end(arg_ptr);
    if (len < 0 || len >= maxlen) {
-      *pool_buf = (char *) realloc_pool_memory(*pool_buf, maxlen + 200);
+      *pool_buf = realloc_pool_memory(*pool_buf, maxlen + 200);
       goto again;
    }
    return len;
 }
 
 
+/*
+ * If we come here, prefix the message with the file:line-number,
+ *  then pass it on to the normal Jmsg routine.
+ */
 void j_msg(char *file, int line, void *jcr, int type, int level, char *fmt,...)
 {
    va_list   arg_ptr;
    int i, len, maxlen;
-   char *pool_buf;
+   POOLMEM *pool_buf;
 
-   pool_buf = (char *) get_pool_memory(PM_EMSG);
+   pool_buf = get_pool_memory(PM_EMSG);
    sprintf(pool_buf, "%s:%d ", file, line);
    i = strlen(pool_buf);
 
@@ -985,7 +1011,7 @@ again:
    len = bvsnprintf(pool_buf+i, maxlen, fmt, arg_ptr);
    va_end(arg_ptr);
    if (len < 0 || len >= maxlen) {
-      pool_buf = (char *) realloc_pool_memory(pool_buf, maxlen + i + 200);
+      pool_buf = realloc_pool_memory(pool_buf, maxlen + i + 200);
       goto again;
    }
 
index 9d111a14d64cc3e51b3f91783dec8954114abc80..432c21b592602b065ec2994040cd2ade97465143 100644 (file)
@@ -59,7 +59,7 @@ typedef struct s_dest {
    char msg_types[nbytes_for_bits(M_MAX+1)]; /* message type mask */
    char *where;                      /* filename/program name */
    char *mail_cmd;                   /* mail command */
-   char *mail_filename;              /* unique mail filename */
+   POOLMEM *mail_filename;           /* unique mail filename */
 } DEST;
 
 /* Message Destination values for dest field of DEST */
index da676363a21f9b14fee3868a03bf3348ced013b0..aabfa3328c6bf88610c2fc26b440f39d956d4e19 100755 (executable)
@@ -174,7 +174,8 @@ void init_resource(int type, struct res_items *items)
 void store_msgs(LEX *lc, struct res_items *item, int index, int pass)
 {
    int token;
-   char *dest, *cmd;
+   char *cmd;
+   POOLMEM *dest;
    int dest_len;
 
    Dmsg2(200, "store_msgs pass=%d code=%d\n", pass, item->code);
@@ -195,7 +196,7 @@ void store_msgs(LEX *lc, struct res_items *item, int index, int pass)
            } else {
               cmd = res_all.res_msgs.mail_cmd;
            }
-           dest = (char *) get_pool_memory(PM_MESSAGE);
+           dest = get_pool_memory(PM_MESSAGE);
            dest_len = 0;
            dest[0] = 0;
            /* Pick up comma separated list of destinations */
@@ -228,13 +229,13 @@ void store_msgs(LEX *lc, struct res_items *item, int index, int pass)
            break;
         case MD_FILE:                /* file */
         case MD_APPEND:              /* append */
-           dest = (char *) get_pool_memory(PM_MESSAGE);
+           dest = get_pool_memory(PM_MESSAGE);
            /* Pick up a single destination */
            token = lex_get_token(lc);    /* scan destination */
            if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
                scan_err1(lc, "expected a message destination, got: %s", lc->str);
            }
-           dest = (char *) check_pool_memory_size(dest, dest_len + lc->str_len + 2);
+           dest = check_pool_memory_size(dest, dest_len + lc->str_len + 2);
            strcpy(dest, lc->str);
            dest_len = lc->str_len;
            token = lex_get_token(lc);
index dd7558be885bdcf004fb84519c4dc8df38ce8c66..60e45dab34a1c406b5a867ff8e23b2fce3481d3b 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * Bacula Thread Read/Write locking code. It permits
- *  multiple readers but only one writer.                
+ *  multiple readers but only one writer.  Note, however,
+ *  that the writer thread is permitted to make multiple
+ *  nested write lock calls.
  *
  *  Kern Sibbald, January MMI
  *
@@ -32,8 +34,6 @@
 
 #include "bacula.h"
 
-#ifdef REALLY_IMPLEMENTED
-
 /*   
  * Initialize a read/write lock
  *
@@ -207,6 +207,7 @@ int rwl_readunlock(rwlock_t *rwl)
 
 /*
  * Lock for write access, wait until locked (or error).
+ *   Multiple nested write locking is permitted.
  */
 int rwl_writelock(rwlock_t *rwl)
 {
@@ -218,12 +219,16 @@ int rwl_writelock(rwlock_t *rwl)
    if ((stat = pthread_mutex_lock(&rwl->mutex)) != 0) {
       return stat;
    }
+   if (rwl->w_active && pthread_equal(rwl->writer_id, pthread_self())) {
+      rwl->w_active++;
+      pthread_mutex_unlock(&rwl->mutex);
+      return 0;
+   }
    if (rwl->w_active || rwl->r_active > 0) {
       rwl->w_wait++;                 /* indicate that we are waiting */
       pthread_cleanup_push(rwl_write_release, (void *)rwl);
       while (rwl->w_active || rwl->r_active > 0) {
-        stat = pthread_cond_wait(&rwl->write, &rwl->mutex);
-        if (stat != 0) {
+        if ((stat = pthread_cond_wait(&rwl->write, &rwl->mutex)) != 0) {
            break;                    /* error, bail out */
         }
       }
@@ -232,6 +237,7 @@ int rwl_writelock(rwlock_t *rwl)
    }
    if (stat == 0) {
       rwl->w_active = 1;             /* we are running */
+      rwl->writer_id = pthread_self(); /* save writer thread's id */
    }
    pthread_mutex_unlock(&rwl->mutex);
    return stat;
@@ -250,10 +256,16 @@ int rwl_writetrylock(rwlock_t *rwl)
    if ((stat = pthread_mutex_lock(&rwl->mutex)) != 0) {
       return stat;
    }
+   if (rwl->w_active && pthread_equal(rwl->writer_id, pthread_self())) {
+      rwl->w_active++;
+      pthread_mutex_unlock(&rwl->mutex);
+      return 0;
+   }
    if (rwl->w_active || rwl->r_active > 0) {
       stat = EBUSY;
    } else {
       rwl->w_active = 1;             /* we are running */
+      rwl->writer_id = pthread_self(); /* save writer thread's id */
    }
    stat2 = pthread_mutex_unlock(&rwl->mutex);
    return (stat == 0 ? stat2 : stat);
@@ -273,14 +285,345 @@ int rwl_writeunlock(rwlock_t *rwl)
    if ((stat = pthread_mutex_lock(&rwl->mutex)) != 0) {
       return stat;
    }
-   rwl->w_active = 0;
-   if (rwl->w_wait > 0) {            /* if writers waiting */
-      stat = pthread_cond_signal(&rwl->write);
-   } else if (rwl->r_wait > 0) {
-      stat = pthread_cond_broadcast(&rwl->read);
+   rwl->w_active--;
+   if (rwl->w_active < 0 || !pthread_equal(pthread_self(), rwl->writer_id)) {
+      Emsg0(M_ABORT, 0, "rwl_writeunlock by non-owner.\n");
+   }
+   if (rwl->w_active > 0) {
+      stat = 0;                      /* writers still active */
+   } else {
+      /* No more writers, awaken someone */
+      if (rwl->r_wait > 0) {        /* if readers waiting */
+        stat = pthread_cond_broadcast(&rwl->read);
+      } else if (rwl->w_wait > 0) {
+        stat = pthread_cond_signal(&rwl->write);
+      }
    }
    stat2 = pthread_mutex_unlock(&rwl->mutex);
    return (stat == 0 ? stat2 : stat);
 }
 
+#ifdef TEST_RWLOCK
+
+#define THREADS     5
+#define DATASIZE   15
+#define ITERATIONS 10000
+
+/*
+ * Keep statics for each thread.
+ */
+typedef struct thread_tag {
+   int thread_num;
+   pthread_t thread_id;
+   int writes;
+   int reads;
+   int interval;
+} thread_t;
+
+/* 
+ * Read/write lock and shared data.
+ */
+typedef struct data_tag {
+   rwlock_t lock;
+   int data;
+   int writes;
+} data_t;
+
+thread_t threads[THREADS];
+data_t data[DATASIZE];
+
+/* 
+ * Thread start routine that uses read/write locks.
+ */
+void *thread_routine(void *arg)
+{
+   thread_t *self = (thread_t *)arg;
+   int repeats = 0;
+   int iteration;
+   int element = 0;
+   int status;
+
+   for (iteration=0; iteration < ITERATIONS; iteration++) {
+      /*
+       * Each "self->interval" iterations, perform an
+       * update operation (write lock instead of read
+       * lock).
+       */
+      if ((iteration % self->interval) == 0) {
+        status = rwl_writelock(&data[element].lock);
+        if (status != 0) {
+            Emsg1(M_ABORT, 0, "Write lock failed. ERR=%s\n", strerror(status));
+        }
+        data[element].data = self->thread_num;
+        data[element].writes++;
+        self->writes++;
+        status = rwl_writeunlock(&data[element].lock);
+        if (status != 0) {
+            Emsg1(M_ABORT, 0, "Write unlock failed. ERR=%s\n", strerror(status));
+        }
+      } else {
+        /*
+         * Look at the current data element to see whether
+         * the current thread last updated it. Count the
+         * times to report later.
+         */
+         status = rwl_readlock(&data[element].lock);
+         if (status != 0) {
+             Emsg1(M_ABORT, 0, "Read lock failed. ERR=%s\n", strerror(status));
+         }
+         self->reads++;
+         if (data[element].data == self->thread_num)
+            repeats++;
+         status = rwl_readunlock(&data[element].lock);
+         if (status != 0) {
+             Emsg1(M_ABORT, 0, "Read unlock failed. ERR=%s\n", strerror(status));
+         }
+      }
+      element++;
+      if (element >= DATASIZE) {
+        element = 0;
+      }
+   }
+   if (repeats > 0) {
+      Dmsg2(000, "Thread %d found unchanged elements %d times\n",
+        self->thread_num, repeats);
+   }
+   return NULL;
+}
+
+int main (int argc, char *argv[])
+{
+    int count;
+    int data_count;
+    int status;
+    unsigned int seed = 1;
+    int thread_writes = 0;
+    int data_writes = 0;
+
+#ifdef sun
+    /*
+     * On Solaris 2.5, threads are not timesliced. To ensure
+     * that our threads can run concurrently, we need to
+     * increase the concurrency level to THREADS.
+     */
+    thr_setconcurrency (THREADS);
+#endif
+
+    /*
+     * Initialize the shared data.
+     */
+    for (data_count = 0; data_count < DATASIZE; data_count++) {
+       data[data_count].data = 0;
+       data[data_count].writes = 0;
+       status = rwl_init (&data[data_count].lock);
+       if (status != 0) {
+           Emsg1(M_ABORT, 0, "Init rwlock failed. ERR=%s\n", strerror(status));
+       }
+    }
+
+    /*
+     * Create THREADS threads to access shared data.
+     */
+    for (count = 0; count < THREADS; count++) {
+       threads[count].thread_num = count + 1;
+       threads[count].writes = 0;
+       threads[count].reads = 0;
+       threads[count].interval = rand_r (&seed) % 71;
+       status = pthread_create (&threads[count].thread_id,
+           NULL, thread_routine, (void*)&threads[count]);
+       if (status != 0) {
+           Emsg1(M_ABORT, 0, "Create thread failed. ERR=%s\n", strerror(status));
+       }
+    }
+
+    /*
+     * Wait for all threads to complete, and collect
+     * statistics.
+     */
+    for (count = 0; count < THREADS; count++) {
+       status = pthread_join (threads[count].thread_id, NULL);
+       if (status != 0) {
+           Emsg1(M_ABORT, 0, "Join thread failed. ERR=%s\n", strerror(status));
+       }
+       thread_writes += threads[count].writes;
+        printf ("%02d: interval %d, writes %d, reads %d\n",
+           count, threads[count].interval,
+           threads[count].writes, threads[count].reads);
+    }
+
+    /*
+     * Collect statistics for the data.
+     */
+    for (data_count = 0; data_count < DATASIZE; data_count++) {
+       data_writes += data[data_count].writes;
+        printf ("data %02d: value %d, %d writes\n",
+           data_count, data[data_count].data, data[data_count].writes);
+       rwl_destroy (&data[data_count].lock);
+    }
+
+    printf ("Total: %d thread writes, %d data writes\n",
+       thread_writes, data_writes);
+    return 0;
+}
+
+#endif
+
+#ifdef TEST_RW_TRY_LOCK
+/*
+ * rwlock_try_main.c
+ *
+ * Demonstrate use of non-blocking read-write locks.
+ *
+ * Special notes: On a Solaris system, call thr_setconcurrency()
+ * to allow interleaved thread execution, since threads are not
+ * timesliced.
+ */
+#include <pthread.h>
+#include "rwlock.h"
+#include "errors.h"
+
+#define THREADS        5
+#define ITERATIONS     1000
+#define DATASIZE       15
+
+/*
+ * Keep statistics for each thread.
+ */
+typedef struct thread_tag {
+    int        thread_num;
+    pthread_t  thread_id;
+    int        r_collisions;
+    int        w_collisions;
+    int        updates;
+    int        interval;
+} thread_t;
+
+/*
+ * Read-write lock and shared data
+ */
+typedef struct data_tag {
+    rwlock_t   lock;
+    int        data;
+    int        updates;
+} data_t;
+
+thread_t threads[THREADS];
+data_t data[DATASIZE];
+
+/*
+ * Thread start routine that uses read-write locks
+ */
+void *thread_routine (void *arg)
+{
+    thread_t *self = (thread_t*)arg;
+    int iteration;
+    int element;
+    int status;
+
+    element = 0;                       /* Current data element */
+
+    for (iteration = 0; iteration < ITERATIONS; iteration++) {
+       if ((iteration % self->interval) == 0) {
+           status = rwl_writetrylock (&data[element].lock);
+           if (status == EBUSY)
+               self->w_collisions++;
+           else if (status == 0) {
+               data[element].data++;
+               data[element].updates++;
+               self->updates++;
+               rwl_writeunlock (&data[element].lock);
+           } else
+                err_abort (status, "Try write lock");
+       } else {
+           status = rwl_readtrylock (&data[element].lock);
+           if (status == EBUSY)
+               self->r_collisions++;
+           else if (status != 0) {
+                err_abort (status, "Try read lock");
+           } else {
+               if (data[element].data != data[element].updates)
+                    printf ("%d: data[%d] %d != %d\n",
+                       self->thread_num, element,
+                       data[element].data, data[element].updates);
+               rwl_readunlock (&data[element].lock);
+           }
+       }
+
+       element++;
+       if (element >= DATASIZE)
+           element = 0;
+    }
+    return NULL;
+}
+
+int main (int argc, char *argv[])
+{
+    int count, data_count;
+    unsigned int seed = 1;
+    int thread_updates = 0, data_updates = 0;
+    int status;
+
+#ifdef sun
+    /*
+     * On Solaris 2.5, threads are not timesliced. To ensure
+     * that our threads can run concurrently, we need to
+     * increase the concurrency level to THREADS.
+     */
+    DPRINTF (("Setting concurrency level to %d\n", THREADS));
+    thr_setconcurrency (THREADS);
+#endif
+
+    /*
+     * Initialize the shared data.
+     */
+    for (data_count = 0; data_count < DATASIZE; data_count++) {
+       data[data_count].data = 0;
+       data[data_count].updates = 0;
+       rwl_init (&data[data_count].lock);
+    }
+
+    /*
+     * Create THREADS threads to access shared data.
+     */
+    for (count = 0; count < THREADS; count++) {
+       threads[count].thread_num = count;
+       threads[count].r_collisions = 0;
+       threads[count].w_collisions = 0;
+       threads[count].updates = 0;
+       threads[count].interval = rand_r (&seed) % ITERATIONS;
+       status = pthread_create (&threads[count].thread_id,
+           NULL, thread_routine, (void*)&threads[count]);
+       if (status != 0)
+            err_abort (status, "Create thread");
+    }
+
+    /*
+     * Wait for all threads to complete, and collect
+     * statistics.
+     */
+    for (count = 0; count < THREADS; count++) {
+       status = pthread_join (threads[count].thread_id, NULL);
+       if (status != 0)
+            err_abort (status, "Join thread");
+       thread_updates += threads[count].updates;
+        printf ("%02d: interval %d, updates %d, "
+                "r_collisions %d, w_collisions %d\n",
+           count, threads[count].interval,
+           threads[count].updates,
+           threads[count].r_collisions, threads[count].w_collisions);
+    }
+
+    /*
+     * Collect statistics for the data.
+     */
+    for (data_count = 0; data_count < DATASIZE; data_count++) {
+       data_updates += data[data_count].updates;
+        printf ("data %02d: value %d, %d updates\n",
+           data_count, data[data_count].data, data[data_count].updates);
+       rwl_destroy (&data[data_count].lock);
+    }
+
+    return 0;
+}
+
 #endif
index c91e8d43d0062970e46883975a574dcf992a3520..79bd96fb9e35e70d000cee3dbef42668bbf156a4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Bacula Thread Read/Write locking code. It permits
- *  multiple readers but only one writer.                
+ *  multiple readers but only one writer.                 
  *
  *  Kern Sibbald, January MMI
  *
 
 typedef struct rwlock_tag {
    pthread_mutex_t   mutex;
-   pthread_cond_t    read;           /* wait for read */
-   pthread_cond_t    write;          /* wait for write */
-   int              valid;           /* set when valid */
-   int              r_active;        /* readers active */
-   int              w_active;        /* writers active */
-   int              r_wait;          /* readers waiting */
-   int              w_wait;          /* writers waiting */
+   pthread_cond_t    read;            /* wait for read */
+   pthread_cond_t    write;           /* wait for write */
+   pthread_t         writer_id;       /* writer's thread id */
+   int               valid;           /* set when valid */
+   int               r_active;        /* readers active */
+   int               w_active;        /* writers active */
+   int               r_wait;          /* readers waiting */
+   int               w_wait;          /* writers waiting */
 } rwlock_t;
 
 #define RWLOCK_VALID  0xfacade
index 9eb02c702a2c1b5f214d815895df86238290708b..f463c7a6782fb880bb9dfb23bc1717ee3e1095f5 100644 (file)
@@ -461,7 +461,7 @@ mount_next_vol:
       }
       /* *****FIXME**** we might do some checking for files too */
       if (dev_is_tape(dev)) {
-         Jmsg(jcr, M_INFO, 0, _("Ready to append at EOM File=%d.\n"), dev_file(dev));
+         Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume at file=%d.\n"), dev_file(dev));
         if (dev->VolCatInfo.VolCatFiles != dev_file(dev) + 1) {
            /* ****FIXME**** this should refuse to write on tape */
             Jmsg(jcr, M_INFO, 0, _("Hey! Num files mismatch! Catalog Files=%d\n"), dev->VolCatInfo.VolCatFiles);
index 3297fe005f53ea709b30f51f26c891759a8fe809..92e4f642eac88adb6f22b963accca9f9df626a80 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.20"
 #define VSTRING "1"
-#define DATE    "19 May 2002"
-#define LSMDATE "19May02"
+#define DATE    "21 May 2002"
+#define LSMDATE "21May02"
 
 /* Debug flags */
 #define DEBUG 1