]> git.sur5r.net Git - bacula/bacula/commitdiff
- Make clean remove old CVS files
authorKern Sibbald <kern@sibbald.com>
Mon, 21 Feb 2005 12:00:23 +0000 (12:00 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 21 Feb 2005 12:00:23 +0000 (12:00 +0000)
- Remove unnecessary image files from Latex directory
- Implement remaining parts of Storage DB record and
  its use in the Director.
- Implement
  FullMaxWaitTime, Differential Max Wait Time, and
  Incremental Max Wait time in Job resource.
- Start work on SD Autochanger code.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1837 91ce42f0-d328-0410-95d8-f526ca767f89

21 files changed:
bacula/Makefile.in
bacula/kernstodo
bacula/src/cats/cats.h
bacula/src/cats/protos.h
bacula/src/cats/sql_create.c
bacula/src/cats/sql_get.c
bacula/src/cats/sql_list.c
bacula/src/cats/sql_update.c
bacula/src/dird/catreq.c
bacula/src/dird/dird.c
bacula/src/dird/dird.h
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/job.c
bacula/src/dird/next_vol.c
bacula/src/dird/recycle.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_label.c
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h
bacula/src/version.h

index 3f805b3ad0cd4115f24d81cf19a406f94e533d8d..a5b99c1e03daec476441347a5aab8fafbd3164cd 100755 (executable)
@@ -182,6 +182,7 @@ clean:
        @$(RMF) *~ 1 2 3 core core.* config.guess console.log console.sum
        @$(RMF) examples/1 examples/2 examples/devices/1 examples/devices/2
        @$(RMF) -r autom4te.cache
+       @find . -name .#* -exec $(RMF) {} \;
 
 
 # clean for distribution
index ccd7730253d446dc4f80c2a9ce3b5d71ad116e33..229c8bc80a5895b2c2dd2567bbbec7856d8e77ef 100644 (file)
@@ -30,8 +30,18 @@ Suggestions for Preben:
 - Optimized bootstrap.
 
 For 1.37:
-- Try to open a device on each Job if it was not opened
-  when the SD started.
+- Add disk seeking on restore.  
+- Add Python writable variable for changing the Priority,
+    Client, Storage, JobStatus (error), ...
+- SD Autochanger work 
+  - Lock all devices when using changer script.
+  - Check if Volume is mounted on another device
+  - Find a free drive if Changer name used.
+- SD Python
+  - Solicit Events
+- FD Python
+  - Python script to save with Python, not save, save with Bacula.
+  - Python script to do backup.
 - Windows restore:
   data-fd: RestoreFiles.2004-12-07_15.56.42 Error:
   > ..\findlib\../../findlib/create_file.c:275 Could not open e:/: ERR=Der
@@ -56,16 +66,12 @@ For 1.37:
   design.
 - Create a new GUI chapter explaining all the GUI programs.
 - Tell the "restore" user when browsing is no longer possible.
-- Add disk seeking on restore.  
 - Cancel command should include JobId in list of Jobs.
 - Require restore via the restore command or make a restore Job
   get the bootstrap file.
-- Add dump of VolSessionId/Time and FileIndex with bls.
 - Make bootstrap file handle multiple MediaTypes (SD)
 - Add offline tape command to Bacula console.
 - Add performance testing hooks
-- Add Python writable variable for changing the Priority,
-    Client, Storage, JobStatus (error), ...
 - Document that Bootstrap files can be written with cataloging
   turned off.
 - Look at adding full Volume and Pool information to a Volume 
@@ -1209,3 +1215,7 @@ Block Position: 0
 - Implement Preben's suggestion to add
   File System Types = ext2, ext3 
   to FileSets, thus simplifying backup of *all* local partitions.
+- Try to open a device on each Job if it was not opened
+  when the SD started.
+- Add dump of VolSessionId/Time and FileIndex with bls.
+
index bcbffd527679d01f153f5db9bf15c24d516ed87f..90f99df892ae3b6d6d5b36a2dc3f2e46d7889853 100644 (file)
@@ -370,10 +370,10 @@ typedef struct s_db {
 
 typedef char **POSTGRESQL_ROW;
 typedef struct pg_field {
-        char         *name;
-        int           max_length;
-        unsigned int  type;
-        unsigned int  flags;       // 1 == not null
+   char         *name;
+   int           max_length;
+   unsigned int  type;
+   unsigned int  flags;       // 1 == not null
 } POSTGRESQL_FIELD;
 
 
@@ -676,8 +676,10 @@ class STORAGE_DBR {
 public:
    DBId_t StorageId;
    char Name[MAX_NAME_LENGTH];        /* Device name */
-   DBId_t MediaTypeId;                /* MediaType */
    int AutoChanger;                   /* Set if autochanger */
+
+   /* Not in database */
+   bool created;                      /* set if created by db_create ... */
 };
 
 class MEDIATYPE_DBR {
@@ -718,6 +720,7 @@ struct MEDIA_DBR {
    int32_t  Recycle;                  /* recycle yes/no */
    int32_t  Slot;                     /* slot in changer */
    int32_t  InChanger;                /* Volume currently in changer */
+   DBId_t   StorageId;                /* Storage record Id */
    uint32_t EndFile;                  /* Last file on volume */
    uint32_t EndBlock;                 /* Last block on volume */
    char VolStatus[20];                /* Volume status */
index 305679d1f639bdc45b4ef8f952ffeee5c474ab3e..0022b75d181e96a090554fdadaca94f31869e060 100644 (file)
@@ -106,6 +106,7 @@ bool db_update_job_start_record(JCR *jcr, B_DB *db, JOB_DBR *jr);
 int  db_update_job_end_record(JCR *jcr, B_DB *db, JOB_DBR *jr);
 int  db_update_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr);
 int  db_update_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pr);
+bool db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr);
 int  db_update_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *mr);
 int  db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr);
 int  db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
index 1265d78a057e83bb785b157759a4f35ec2bcbd2c..8fe07996aa149f2543f7ff0d476c77582a6412c9 100644 (file)
@@ -215,7 +215,7 @@ db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
 bool
 db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr)
 {
-   bool stat;       
+   bool ok;
    char ed1[30], ed2[30];
 
    Dmsg0(200, "In create Device\n");
@@ -236,69 +236,81 @@ db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr)
 
    /* Must create it */
    Mmsg(mdb->cmd,
-"INSERT INTO Device (Name,MediaTypeId,StorageId) "
-"VALUES ('%s',%s,%s)",
+"INSERT INTO Device (Name,MediaTypeId,StorageId) VALUES ('%s',%s,%s)",
                  dr->Name,
                  edit_uint64(dr->MediaTypeId, ed1),
-                 edit_uint64(dr->StorageId, ed2));
+                 edit_int64(dr->StorageId, ed2));
    Dmsg1(200, "Create Device: %s\n", mdb->cmd);
    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
       Mmsg2(&mdb->errmsg, _("Create db Device record %s failed: ERR=%s\n"),
            mdb->cmd, sql_strerror(mdb));
       dr->DeviceId = 0;
-      stat = false;
+      ok = false;
    } else {
       dr->DeviceId = sql_insert_id(mdb, _("Device"));
-      stat = true;
+      ok = true;
    }
    db_unlock(mdb);
-   return stat;
+   return ok;
 }
 
+
+
 /*
- * Create Unique storage record
+ * Create a Unique record for Storage -- no duplicates
  * Returns: false on failure
- *         true  on success
+ *         true  on success with id in sr->StorageId
  */
-bool
-db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
+bool db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
 {
-   bool stat;       
+   SQL_ROW row;
+   bool ok;
 
-   Dmsg0(200, "In create storage\n");
    db_lock(mdb);
-   Mmsg(mdb->cmd, "SELECT StorageId,Name FROM Storage WHERE Name='%s'", sr->Name);
-   Dmsg1(200, "selectstorage: %s\n", mdb->cmd);
+   Mmsg(mdb->cmd, "SELECT StorageId,AutoChanger FROM Storage WHERE Name='%s'", sr->Name);
 
+   sr->StorageId = 0;
+   sr->created = false;
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
       mdb->num_rows = sql_num_rows(mdb);
-      if (mdb->num_rows > 0) {
-         Mmsg1(&mdb->errmsg, _("Storage record %s already exists\n"), sr->Name);
+      /* If more than one, report error, but return first row */
+      if (mdb->num_rows > 1) {
+         Mmsg1(&mdb->errmsg, _("More than one Storage record!: %d\n"), (int)(mdb->num_rows));
+         Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
+      }
+      if (mdb->num_rows >= 1) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
+            Mmsg1(&mdb->errmsg, _("error fetching Storage row: %s\n"), sql_strerror(mdb));
+            Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
+           sql_free_result(mdb);
+           db_unlock(mdb);
+           return false;
+        }
+        sr->StorageId = str_to_int64(row[0]);
+        sr->AutoChanger = atoi(row[1]);   /* bool */
         sql_free_result(mdb);
         db_unlock(mdb);
-        return false;
+        return true;
       }
       sql_free_result(mdb);
    }
 
    /* Must create it */
-   Mmsg(mdb->cmd,
-"INSERT INTO Storage (Name,AutoChanger) "
-"VALUES ('%s',%d)",
-                 sr->Name,
-                 sr->AutoChanger);
-   Dmsg1(200, "Create storage: %s\n", mdb->cmd);
+   Mmsg(mdb->cmd, "INSERT INTO Storage (Name,AutoChanger)"
+        " VALUES ('%s',%d)", sr->Name, sr->AutoChanger);
+
    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
-      Mmsg2(&mdb->errmsg, _("Create db storage record %s failed: ERR=%s\n"),
+      Mmsg2(&mdb->errmsg, _("Create DB Storage record %s failed. ERR=%s\n"),
            mdb->cmd, sql_strerror(mdb));
-      sr->StorageId = 0;
-      stat = false;
+      Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
+      ok = false;
    } else {
       sr->StorageId = sql_insert_id(mdb, _("Storage"));
-      stat = true;
+      sr->created = true;
+      ok = true;
    }
    db_unlock(mdb);
-   return stat;
+   return ok;
 }
 
 
@@ -349,8 +361,6 @@ db_create_mediatype_record(JCR *jcr, B_DB *mdb, MEDIATYPE_DBR *mr)
 }
 
 
-
-
 /*
  * Create Media record. VolumeName and non-zero Slot must be unique
  *
@@ -361,7 +371,7 @@ int
 db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
 {
    int stat;
-   char ed1[30], ed2[30], ed3[30], ed4[30], ed5[30], ed6[50], ed7[50];
+   char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50], ed7[50], ed8[50];
    struct tm tm;
 
    db_lock(mdb);
@@ -385,8 +395,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
 "INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes,"
 "Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
 "VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts,"
-"EndFile,EndBlock,LabelType) "
-"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d)",
+"EndFile,EndBlock,LabelType,StorageId) "
+"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d,%s)",
                  mr->VolumeName,
                  mr->MediaType, mr->PoolId,
                  edit_uint64(mr->MaxVolBytes,ed1),
@@ -403,7 +413,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
                  edit_uint64(mr->VolReadTime, ed6),
                  edit_uint64(mr->VolWriteTime, ed7),
                  mr->VolParts,
-                 mr->LabelType
+                 mr->LabelType,
+                 edit_int64(mr->StorageId, ed8) 
                  );
 
 
@@ -438,8 +449,6 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
    return stat;
 }
 
-
-
 /*
  * Create a Unique record for the client -- no duplicates
  * Returns: 0 on failure
@@ -505,6 +514,9 @@ int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
 }
 
 
+
+
+
 /*
  * Create a Unique record for the counter -- no duplicates
  * Returns: 0 on failure
index 968ebd865db5c6ecd986f29a9ed8798fb6aba532..c7fbea4b8bb19c42675716445cd560771524554f 100644 (file)
@@ -835,7 +835,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
          "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
-         "EndFile,EndBlock,VolParts,LabelType,LabelDate "
+         "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
          "FROM Media WHERE MediaId=%s", 
         edit_int64(mr->MediaId, ed1));
    } else {                          /* find by name */
@@ -843,7 +843,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
          "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
-         "EndFile,EndBlock,VolParts,LabelType,LabelDate "
+         "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
          "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
    }
 
@@ -891,6 +891,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
            mr->LabelType = str_to_int64(row[26]);
             bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
            mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
+           mr->StorageId = str_to_int64(row[28]);
            stat = mr->MediaId;
         }
       } else {
index 7a1d17731165e795cb36e579552d89442a570b82..c97c5a4ad6a200194a8e5bd79f9cf1eae0f49d6a 100644 (file)
@@ -142,7 +142,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr,
             "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
             "VolCapacityBytes,VolStatus,Recycle,VolRetention,"
             "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger,"
-            "EndFile,EndBlock,VolParts,LabelType"
+            "EndFile,EndBlock,VolParts,LabelType,StorageId"
             " FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName);
       } else {
          Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId,"
@@ -150,7 +150,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr,
             "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites,"
             "VolCapacityBytes,VolStatus,Recycle,VolRetention,"
             "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger,"
-            "EndFile,EndBlock,VolParts,LabelType"
+            "EndFile,EndBlock,VolParts,LabelType,StorageId"
             " FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", 
            edit_int64(mdbr->PoolId, ed1));
       }
index f02578ff05490b30a2c8e8b866c02d7940d4a6f5..e3f0779239449d715c0d87fca65d5e9731540056 100644 (file)
@@ -258,6 +258,22 @@ db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
    return stat;
 }
 
+bool
+db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
+{
+   int stat;
+   char ed1[50];
+
+   db_lock(mdb);
+   Mmsg(mdb->cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s", 
+      sr->AutoChanger, edit_int64(sr->StorageId, ed1));
+
+   stat = UPDATE_DB(jcr, mdb, mdb->cmd);
+   db_unlock(mdb);
+   return stat;
+}
+
+
 /*
  * Update the Media Record at end of Session
  *
@@ -271,7 +287,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
    time_t ttime;
    struct tm tm;
    int stat;
-   char ed1[30], ed2[30], ed3[30], ed4[30];
+   char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
 
 
    Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
@@ -297,47 +313,35 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
       strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
       Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
            "WHERE VolumeName='%s'", dt, mr->VolumeName);
-      stat = UPDATE_DB(jcr, mdb, mdb->cmd);
+      UPDATE_DB(jcr, mdb, mdb->cmd);
    }
 
    if (mr->LastWritten != 0) {
       ttime = mr->LastWritten;
       localtime_r(&ttime, &tm);
       strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
-
-      Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u,"
-           "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
-           "VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s',"
-           "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d,"
-           "LabelType=%d"
-           " WHERE VolumeName='%s'",
-          mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
-          mr->VolMounts, mr->VolErrors, mr->VolWrites,
-          edit_uint64(mr->MaxVolBytes, ed2), dt,
-          mr->VolStatus, mr->Slot, mr->InChanger,
-          edit_uint64(mr->VolReadTime, ed3),
-          edit_uint64(mr->VolWriteTime, ed4),
-          mr->VolParts,
-          mr->LabelType,
-          mr->VolumeName);
-   } else {
-      Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u,"
-           "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
-           "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s',"
-           "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d,"
-           "LabelType=%d"
-           " WHERE VolumeName='%s'",
-          mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
-          mr->VolMounts, mr->VolErrors, mr->VolWrites,
-          edit_uint64(mr->MaxVolBytes, ed2),
-          mr->VolStatus, mr->Slot, mr->InChanger,
-          edit_uint64(mr->VolReadTime, ed3),
-          edit_uint64(mr->VolWriteTime, ed4),
-          mr->VolParts,
-          mr->LabelType,
-          mr->VolumeName);
+      Mmsg(mdb->cmd, "UPDATE Media Set LastWritten='%s' "
+           "WHERE VolumeName='%s'", dt, mr->VolumeName);
+      UPDATE_DB(jcr, mdb, mdb->cmd);
    }
 
+   Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u,"
+        "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u,"
+        "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s',"
+        "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d,"
+        "LabelType=%d,StorageId=%s"
+        " WHERE VolumeName='%s'",
+       mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1),
+       mr->VolMounts, mr->VolErrors, mr->VolWrites,
+       edit_uint64(mr->MaxVolBytes, ed2),
+       mr->VolStatus, mr->Slot, mr->InChanger,
+       edit_uint64(mr->VolReadTime, ed3),
+       edit_uint64(mr->VolWriteTime, ed4),
+       mr->VolParts,
+       mr->LabelType,
+       edit_int64(mr->StorageId, ed5),
+       mr->VolumeName);
+
    Dmsg1(400, "%s\n", mdb->cmd);
 
    stat = UPDATE_DB(jcr, mdb, mdb->cmd);
@@ -406,9 +410,9 @@ db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
    char ed1[50], ed2[50];
    if (mr->InChanger != 0 && mr->Slot != 0) {
       Mmsg(mdb->cmd, "UPDATE Media SET InChanger=0 WHERE "
-           "Slot=%d AND PoolId=%s AND MediaId!=%s",
+           "Slot=%d AND StorageId=%s AND MediaId!=%s",
            mr->Slot, 
-           edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2));
+           edit_int64(mr->StorageId, ed1), edit_int64(mr->MediaId, ed2));
       Dmsg1(400, "%s\n", mdb->cmd);
       UPDATE_DB(jcr, mdb, mdb->cmd);
    }
index a1eb4fc92684082fe7500ad7979f2a8a464c1403..fd53c276c83f1ea03f9b2b891864a324daf133e0 100644 (file)
@@ -250,9 +250,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
        * Check if it has expired, and if not update the DB. Note, if
        *   Volume has expired, has_volume_expired() will update the DB.
        */
-      if (has_volume_expired(jcr, &mr)) {
-        send_volume_info_to_storage_daemon(jcr, bs, &mr);
-      } else if (db_update_media_record(jcr, jcr->db, &mr)) {
+      if (has_volume_expired(jcr, &mr) || db_update_media_record(jcr, jcr->db, &mr)) {
         send_volume_info_to_storage_daemon(jcr, bs, &mr);
       } else {
          Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"),
index 7a419f49e99f715ee02a9dc28779cfd1e2005187..431583aa2dd899ed6354c597f7d95a616a28d4a9 100644 (file)
@@ -641,7 +641,6 @@ static int check_resources()
         create_pool(NULL, db, pool, POOL_OP_UPDATE);  /* update request */
       }
 
-      /* ***FIXME*** we need to update store and media_type records */
       STORE *store;
       foreach_res(store, R_STORAGE) {
         STORAGE_DBR sr;
@@ -653,10 +652,13 @@ static int check_resources()
         } else {
            mr.MediaTypeId = 0;
         }
-        sr.MediaTypeId = mr.MediaTypeId;
         bstrncpy(sr.Name, store->name(), sizeof(sr.Name));
         sr.AutoChanger = store->autochanger;
         db_create_storage_record(NULL, db, &sr);
+        store->StorageId = sr.StorageId;   /* set storage Id */
+        if (!sr.created) {                 /* if not created, update it */
+           db_update_storage_record(NULL, db, &sr);
+        }
       }
 
       /* Loop over all counters, defining them in each database */
index 37136a123a8548d300ea6e1ded30c5febe935603..fe00fffb0c30c0e72aebecfb94806b97563fc559 100644 (file)
@@ -6,7 +6,7 @@
  *    Version $Id$
  */
 /*
-   Copyright (C) 2000-2004 Kern Sibbald and John Walker
+   Copyright (C) 2000-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
index 5b812ead8eeedc653427de8256c7404ecce41940..99d9006c4cd7da0fa2c77e9695a22fc6f1d49ab5 100644 (file)
@@ -221,6 +221,9 @@ RES_ITEM job_items[] = {
    {"writebootstrap",store_dir, ITEM(res_job.WriteBootstrap), 0, 0, 0},
    {"replace",  store_replace,  ITEM(res_job.replace), 0, ITEM_DEFAULT, REPLACE_ALWAYS},
    {"maxruntime",   store_time, ITEM(res_job.MaxRunTime), 0, 0, 0},
+   {"fullmaxwaittime",  store_time, ITEM(res_job.FullMaxWaitTime), 0, 0, 0},
+   {"incrementalmaxwaittime",  store_time, ITEM(res_job.IncMaxWaitTime), 0, 0, 0},
+   {"differentialmaxwaittime",  store_time, ITEM(res_job.DiffMaxWaitTime), 0, 0, 0},
    {"maxwaittime",  store_time, ITEM(res_job.MaxWaitTime), 0, 0, 0},
    {"maxstartdelay",store_time, ITEM(res_job.MaxStartDelay), 0, 0, 0},
    {"jobretention", store_time, ITEM(res_job.JobRetention),  0, 0, 0},
@@ -477,11 +480,12 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       break;
    case R_STORAGE:
       sendit(sock, "Storage: name=%s address=%s SDport=%d MaxJobs=%u\n"
-"      DeviceName=%s MediaType=%s\n",
+"      DeviceName=%s MediaType=%s StorageId=%s\n",
         res->res_store.hdr.name, res->res_store.address, res->res_store.SDport,
         res->res_store.MaxConcurrentJobs,
         res->res_store.dev_name(),
-        res->res_store.media_type);
+        res->res_store.media_type,
+        edit_int64(res->res_store.StorageId, ed1));
       break;
    case R_CATALOG:
       sendit(sock, "Catalog: name=%s address=%s DBport=%d db_name=%s\n"
index b1542aa1b3fae741d1012f649ba80fbac962cbbe..745dd554e2e51177e501714ec3b02953fbc206d2 100644 (file)
@@ -220,6 +220,8 @@ public:
    uint32_t NumConcurrentJobs;        /* number of concurrent jobs running */
    int enable_ssl;                    /* Use SSL */
 
+   int64_t StorageId;                 /* Set from Storage DB record */
+
    char *dev_name() const;
    char *name() const;
 };
@@ -255,6 +257,9 @@ public:
    int   replace;                     /* How (overwrite, ..) */
    utime_t MaxRunTime;                /* max run time in seconds */
    utime_t MaxWaitTime;               /* max blocking time in seconds */
+   utime_t FullMaxWaitTime;           /* Max Full job wait time */
+   utime_t DiffMaxWaitTime;           /* Max Differential job wait time */
+   utime_t IncMaxWaitTime;            /* Max Incremental job wait time */
    utime_t MaxStartDelay;             /* max start delay in seconds */
    int PrefixLinks;                   /* prefix soft links with Where path */
    int PruneJobs;                     /* Force pruning of Jobs */
index 1107ef425b1049a790144075acc146873fe7ac4a..da1d5d29aeda56df1ed1cf9920f75e85a5963989 100644 (file)
@@ -436,18 +436,32 @@ static void job_monitor_watchdog(watchdog_t *self)
 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
 {
    bool cancel = false;
+   bool ok_to_cancel = false;
+   JOB *job = jcr->job;
 
-   if (jcr->job->MaxWaitTime == 0) {
+   if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
+       job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
       return false;
-   }
-   if ((watchdog_time - jcr->start_time) < jcr->job->MaxWaitTime) {
-      Dmsg3(800, "Job %p (%s) with MaxWaitTime %d not expired\n",
-           jcr, jcr->Job, jcr->job->MaxWaitTime);
+   } 
+   if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
+        (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
+      ok_to_cancel = true;
+   } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
+        (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
+      ok_to_cancel = true;
+   } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
+        (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
+      ok_to_cancel = true;
+   } else if (job->MaxWaitTime != 0 &&
+        (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
+      ok_to_cancel = true;
+   }
+   if (!ok_to_cancel) {
       return false;
    }
    Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, "
          "checking status\n",
-        jcr->JobId, jcr->Job, jcr->job->MaxWaitTime);
+        jcr->JobId, jcr->Job, job->MaxWaitTime);
    switch (jcr->JobStatus) {
    case JS_Created:
    case JS_Blocked:
index 34b84b9133660cdbd53a17cfa25f377b52a9596c..bf44fc84427889ab333047055d289af2fc6032bb 100644 (file)
@@ -9,7 +9,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2001-2004 Kern Sibbald and John Walker
+   Copyright (C) 2001-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -71,7 +71,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create)
          * 2. Try finding a recycled volume
          */
         ok = find_recycled_volume(jcr, InChanger, mr);
-        Dmsg2(100, "find_recycled_volume %d FW=%d\n", ok, mr->FirstWritten);
+         Dmsg2(100, "find_recycled_volume %d FW=%d\n", ok, mr->FirstWritten);
         if (!ok) {
            /*
             * 3. Try recycling any purged volume
@@ -89,10 +89,10 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create)
                     continue;           /* retry again accepting any volume */
                  }
               }
-              Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr->FirstWritten);
+               Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr->FirstWritten);
               if (!ok && create) {
                  /*
-                  * 5. Try "creating" a new Volume
+                   * 5. Try "creating" a new Volume
                   */
                  ok = newVolume(jcr, mr);
               }
@@ -104,32 +104,32 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create)
          */
         if (!ok && (jcr->pool->purge_oldest_volume ||
                     jcr->pool->recycle_oldest_volume)) {
-           Dmsg2(200, "No next volume found. PurgeOldest=%d\n RecyleOldest=%d",
+            Dmsg2(200, "No next volume found. PurgeOldest=%d\n RecyleOldest=%d",
                jcr->pool->purge_oldest_volume, jcr->pool->recycle_oldest_volume);
            /* Find oldest volume to recycle */
            ok = db_find_next_volume(jcr, jcr->db, -1, InChanger, mr);
-           Dmsg1(400, "Find oldest=%d\n", ok);
+            Dmsg1(400, "Find oldest=%d\n", ok);
            if (ok) {
               UAContext *ua;
-              Dmsg0(400, "Try purge.\n");
+               Dmsg0(400, "Try purge.\n");
               /*
                * 5.  Try to purging oldest volume only if not UA calling us.
                */
               ua = new_ua_context(jcr);
               if (jcr->pool->purge_oldest_volume && create) {
-                 Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr->VolumeName);
+                  Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr->VolumeName);
                  ok = purge_jobs_from_volume(ua, mr);
               /*
                * 5. or try recycling the oldest volume
                */
               } else if (jcr->pool->recycle_oldest_volume) {
-                 Jmsg(jcr, M_INFO, 0, _("Pruning oldest volume \"%s\"\n"), mr->VolumeName);
+                  Jmsg(jcr, M_INFO, 0, _("Pruning oldest volume \"%s\"\n"), mr->VolumeName);
                  ok = prune_volume(ua, mr);
               }
               free_ua_context(ua);
               if (ok) {
                  ok = recycle_volume(jcr, mr);
-                 Dmsg1(400, "Recycle after purge oldest=%d\n", ok);
+                  Dmsg1(400, "Recycle after purge oldest=%d\n", ok);
               }
            }
         }
@@ -167,30 +167,30 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr)
    if (strcmp(mr->VolStatus, "Append") == 0 && mr->VolJobs > 0) {
       /* First handle Max Volume Bytes */
       if ((mr->MaxVolBytes > 0 && mr->VolBytes >= mr->MaxVolBytes)) {
-        Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. "
-            "Marking Volume \"%s\" as Full.\n"), mr->VolumeName);
-        bstrncpy(mr->VolStatus, "Full", sizeof(mr->VolStatus));
+         Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. "
+             "Marking Volume \"%s\" as Full.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Full", sizeof(mr->VolStatus));
         expired = true;
 
       /* Now see if Volume should only be used once */
       } else if (mr->VolBytes > 0 && jcr->pool->use_volume_once) {
-        Jmsg(jcr, M_INFO, 0, _("Volume used once. "
-            "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
-        bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+         Jmsg(jcr, M_INFO, 0, _("Volume used once. "
+             "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
         expired = true;
 
       /* Now see if Max Jobs written to volume */
       } else if (mr->MaxVolJobs > 0 && mr->MaxVolJobs <= mr->VolJobs) {
-        Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. "
-            "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
-        bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+         Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. "
+             "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
         expired = true;
 
       /* Now see if Max Files written to volume */
       } else if (mr->MaxVolFiles > 0 && mr->MaxVolFiles <= mr->VolFiles) {
-        Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. "
-            "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
-        bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+         Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. "
+             "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+         bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
         expired = true;
 
       /* Finally, check Use duration expiration */
@@ -198,9 +198,9 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr)
         utime_t now = time(NULL);
         /* See if Vol Use has expired */
         if (mr->VolUseDuration <= (now - mr->FirstWritten)) {
-           Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. "
-              "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
-           bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
+            Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. "
+               "Marking Volume \"%s\" as Used.\n"), mr->VolumeName);
+            bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus));
            expired = true;
         }
       }
@@ -208,7 +208,7 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr)
    if (expired) {
       /* Need to update media */
       if (!db_update_media_record(jcr, jcr->db, mr)) {
-        Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"),
+         Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"),
              mr->VolumeName, db_strerror(jcr->db));
       }
    }
@@ -247,12 +247,12 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r
     */
    if (strcmp(mr->VolStatus, "Purged") == 0) {
       if (recycle_volume(jcr, mr)) {
-        Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName);
+         Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName);
         *reason = NULL;
         return;
       } else {
-        /* In principle this shouldn't happen */
-        *reason = "and recycling of current volume failed";
+         /* In principle this shouldn't happen */
+         *reason = "and recycling of current volume failed";
         return;
       }
    }
@@ -268,8 +268,8 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r
     */
    if ((mr->LastWritten + mr->VolRetention) < (utime_t)time(NULL)
         && mr->Recycle && jcr->pool->recycle_current_volume
-        && (strcmp(mr->VolStatus, "Full") == 0 ||
-           strcmp(mr->VolStatus, "Used") == 0)) {
+         && (strcmp(mr->VolStatus, "Full") == 0 ||
+            strcmp(mr->VolStatus, "Used") == 0)) {
       /*
        * Attempt prune of current volume to see if we can
        * recycle it for use.
@@ -283,15 +283,15 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r
       if (ok) {
         /* If fully purged, recycle current volume */
         if (recycle_volume(jcr, mr)) {
-           Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName);
+            Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName);
            *reason = NULL;
         } else {
-           *reason = "but should be Append, Purged or Recycle (recycling of the "
-              "current volume failed)";
+            *reason = "but should be Append, Purged or Recycle (recycling of the "
+               "current volume failed)";
         }
       } else {
-        *reason = "but should be Append, Purged or Recycle (cannot automatically "
-           "recycle current volume, as it still contains unpruned data)";
+         *reason = "but should be Append, Purged or Recycle (cannot automatically "
+            "recycle current volume, as it still contains unpruned data)";
       }
    }
 }
index a4e15bb9065a9853ee497b888daaa4f0d785df20..c242d1bc8116eddb2ce0cf475081d0dd8cc097d0 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /*
-   Copyright (C) 2002-2004 Kern Sibbald and John Walker
+   Copyright (C) 2002-20054 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
index 273d1500e880e11f21babc615bc7bbb4f2e90f32..8146d281d4d8a3b82edfdf4295aeeea25a9581dd 100644 (file)
@@ -862,7 +862,6 @@ static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *o
       if (!db_update_pool_record(ua->jcr, ua->db, &pr)) {
          bsendmsg(ua, "%s", db_strerror(ua->db));
       }
-      db_make_inchanger_unique(ua->jcr, ua->db, mr);
    }
    db_unlock(ua->db);
    free_pool_memory(query);
index 423678c9338ca960c72a19afc2d81a96bb5c371e..eecd1ee9469db0cc644a58728c54487ae2ca0634 100644 (file)
@@ -213,6 +213,7 @@ int update_slots(UAContext *ua)
         memset(&mr, 0, sizeof(mr));
         mr.Slot = vl->Slot;
         mr.InChanger = 1;
+        mr.StorageId = store->StorageId;
         /* Set InChanger to zero for this Slot */
         db_lock(ua->db);
         db_make_inchanger_unique(ua->jcr, ua->db, &mr);
@@ -224,30 +225,32 @@ int update_slots(UAContext *ua)
       bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName));
       db_lock(ua->db);
       if (db_get_media_record(ua->jcr, ua->db, &mr)) {
-         if (mr.Slot != vl->Slot || !mr.InChanger) {
-            mr.Slot = vl->Slot;
-            mr.InChanger = 1;
-            if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
-                bsendmsg(ua, "%s", db_strerror(ua->db));
-            } else {
-               bsendmsg(ua, _(
-                  "Catalog record for Volume \"%s\" updated to reference slot %d.\n"),
-                 mr.VolumeName, mr.Slot);
-            }
-         } else {
-             bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"),
-               mr.VolumeName);
-         }
-         db_unlock(ua->db);
-         continue;
+        if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) {
+           mr.Slot = vl->Slot;
+           mr.InChanger = 1;
+           mr.StorageId = store->StorageId;
+           if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
+               bsendmsg(ua, "%s", db_strerror(ua->db));
+           } else {
+              bsendmsg(ua, _(
+                 "Catalog record for Volume \"%s\" updated to reference slot %d.\n"),
+                mr.VolumeName, mr.Slot);
+           }
+        } else {
+            bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"),
+              mr.VolumeName);
+        }
+        db_unlock(ua->db);
+        continue;
       } else {
-          bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"),
+         bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"),
             mr.VolumeName);
       }
       db_unlock(ua->db);
    }
    memset(&mr, 0, sizeof(mr));
    mr.InChanger = 1;
+   mr.StorageId = store->StorageId;
    db_lock(ua->db);
    for (int i=1; i<max_slots; i++) {
       if (slot_list[i]) {
@@ -491,11 +494,11 @@ static void label_from_barcodes(UAContext *ua)
          if (mr.VolBytes != 0) {
              bsendmsg(ua, _("Media record for Slot %d Volume \"%s\" already exists.\n"),
                vl->Slot, mr.VolumeName);
-            if (!mr.InChanger) {
-               mr.InChanger = 1;
-               if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
-                   bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db));
-               }
+            mr.Slot = vl->Slot;
+            mr.InChanger = 1;
+            mr.StorageId = store->StorageId;
+            if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
+                bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db));
             }
             continue;
          }
index dd2fa42415ffee89e54fc7205d9e7cee99cf5151..4589a1daa734b11357cde13befbcc79c6c249601 100644 (file)
@@ -443,6 +443,8 @@ void save_resource(int type, RES_ITEM *items, int pass)
     * record.
     */
    if (pass == 2) {
+      DEVRES *dev;
+      int errstat;
       switch (type) {
       /* Resources not containing a resource */
       case R_DIRECTOR:
@@ -464,6 +466,14 @@ void save_resource(int type, RES_ITEM *items, int pass)
         }
         /* we must explicitly copy the device alist pointer */
         res->res_changer.device   = res_all.res_changer.device;
+        foreach_alist(dev, res->res_changer.device) {
+           dev->changer_res = (AUTOCHANGER *)&res->res_changer;
+        }
+        if ((errstat = pthread_mutex_init(&dev->changer_res->changer_mutex, NULL)) != 0) {
+           berrno be;
+            Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"), 
+                 be.strerror(errstat));
+        }
         break;
       default:
          printf("Unknown resource type %d\n", type);
index 448f41a879fb14dbe20e313575f3f1e5b9a41316..44a9331a126a33b080b583f0e6f8a3cbb6446d96 100644 (file)
@@ -71,6 +71,15 @@ public:
 };
 typedef struct s_res_store STORES;
 
+class AUTOCHANGER {
+public:
+   RES hdr;
+   alist *device;
+   char *changer_name;                /* Changer device name */
+   char *changer_command;             /* Changer command  -- external program */
+   pthread_mutex_t changer_mutex;     /* One changer operation at a time */
+};
+
 /* Device specific definitions */
 class DEVRES {
 public:
@@ -108,16 +117,11 @@ public:
    char *write_part_command;          /* Write part command */
    char *free_space_command;          /* Free space command */
    
+   /* The following are set at runtime */
    DEVICE *dev;                       /* Pointer to phyical dev -- set at runtime */
+   AUTOCHANGER *changer_res;          /* pointer to changer res if any */
 };
 
-class AUTOCHANGER {
-public:
-   RES hdr;
-   alist *device;
-   char *changer_name;                /* Changer device name */
-   char *changer_command;             /* Changer command  -- external program */
-};
 
 union URES {
    DIRRES      res_dir;
index 698129b2c1a53788882f4bfd81da8ba830fac4b0..7246bc8f765e951dedc5ba3f9a350ed69684e293 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #undef  VERSION
 #define VERSION "1.37.4"
-#define BDATE   "18 February 2005"
-#define LSMDATE "18Feb05"
+#define BDATE   "20 February 2005"
+#define LSMDATE "20Feb05"
 
 /* Debug flags */
 #undef  DEBUG