- Document FInclude ...
 - Document need to add "-u root" to most of MySQL script calls
   (./create_mys... ./make_my...).
+- Document recycling algorithm.
 
           
 Testing to do: (painful)
 - Test multiple simultaneous Volumes
 - Test of last block is correct in JobMedia when splitting file 
   over two volumes.
+- Test recycling and purging (code changed in db_find_next_volume and
+  in recycle.c).
 - Figure out how to use ssh or stunnel to protect Bacula communications.
 
 For 1.31 release:
 
    db_lock(mdb);
    if (item == -1) {      /* find oldest volume */
       /* Find oldest volume */
-      Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
-VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,\
-VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot,\
-FirstWritten,LastWritten \
-FROM Media WHERE PoolId=%d AND MediaType='%s' AND VolStatus IN ('Full',\
-'Recycle','Purged','Used') \
-ORDER BY FirstWritten", mr->PoolId, mr->MediaType); 
+      Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
+"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
+"VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot,"
+"FirstWritten,LastWritten "
+"FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus IN ('Full',"
+"'Recycle','Purged','Used','Append') "
+"ORDER BY LastWritten", mr->PoolId, mr->MediaType); 
      item = 1;
    } else {
       /* Find next available volume */
-      Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,\
-VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,\
-VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot,\
-FirstWritten,LastWritten \
-FROM Media WHERE PoolId=%d AND MediaType='%s' AND VolStatus='%s' \
-ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus); 
+      Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
+"VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
+"VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot,"
+"FirstWritten,LastWritten "
+"FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' "
+"ORDER BY MediaId", mr->PoolId, mr->MediaType, mr->VolStatus); 
    }
    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
       db_unlock(mdb);
 
    Dmsg1(200, "catreq %s", bs->msg);
    if (sscanf(bs->msg, Find_media, &Job, &index) == 2) {
       mr.PoolId = jcr->PoolId;
-      strcpy(mr.MediaType, jcr->store->media_type);
+      bstrncpy(mr.MediaType, jcr->store->media_type, sizeof(mr.MediaType));
       Dmsg2(120, "CatReq FindMedia: Id=%d, MediaType=%s\n",
         mr.PoolId, mr.MediaType);
       /*
       ok = db_find_next_volume(jcr, jcr->db, index, &mr);  
       Dmsg2(100, "catreq after find_next_vol ok=%d FW=%d\n", ok, mr.FirstWritten);
       if (!ok) {
-         Dmsg1(200, "No next volume found. RecycleOldest=%d\n",
-            jcr->pool->recycle_oldest_volume);
-        if (jcr->pool->recycle_oldest_volume) {
-            Dmsg0(200, "Request to find oldest volume.\n");
+        /* Well, try finding recycled tapes */
+        ok = find_recycled_volume(jcr, &mr);
+         Dmsg2(100, "find_recycled_volume1 %d FW=%d\n", ok, mr.FirstWritten);
+        if (!ok) {
+           prune_volumes(jcr);  
+           ok = recycle_oldest_purged_volume(jcr, &mr);
+            Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr.FirstWritten);
+           if (!ok) {
+              /* See if we can create a new Volume */
+              ok = newVolume(jcr, &mr);
+           }
+        }
+
+        if (!ok && jcr->pool->recycle_oldest_volume) {
+            Dmsg1(200, "No next volume found. RecycleOldest=%d\n",
+               jcr->pool->recycle_oldest_volume);
            /* Find oldest volume to recycle */
            ok = db_find_next_volume(jcr, jcr->db, -1, &mr);
             Dmsg1(400, "Find oldest=%d\n", ok);
                Dmsg0(400, "Try purge.\n");
               /* Try to purge oldest volume */
               create_ua_context(jcr, &ua);
+               Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr.VolumeName);
               ok = purge_jobs_from_volume(&ua, &mr);
               free_ua_context(&ua);
               if (ok) {
               }
            }
         }
-        if (!ok) {
-           /* Well, try finding recycled tapes */
-           ok = find_recycled_volume(jcr, &mr);
-            Dmsg2(100, "find_recycled_volume1 %d FW=%d\n", ok, mr.FirstWritten);
-           if (!ok) {
-              prune_volumes(jcr);  
-              ok = recycle_oldest_purged_volume(jcr, &mr);
-               Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr.FirstWritten);
-              if (!ok) {
-                 /* See if we can create a new Volume */
-                 ok = newVolume(jcr, &mr);
-              }
-           }
-        }
       }
       /* Check if use duration has expired */
       Dmsg2(100, "VolJobs=%d FirstWritten=%d\n", mr.VolJobs, mr.FirstWritten);
 
    /* Find oldest Media record */
    if (row[1] && strcmp(row[1], oldest->LastWritten) < 0) {
       oldest->MediaId = atoi(row[0]);
-      strcpy(oldest->LastWritten, row[1]);
+      bstrncpy(oldest->LastWritten, row[1], sizeof(oldest->LastWritten));
       Dmsg1(100, "New oldest %s\n", row[1]);
    }
    return 1;
    if (db_find_next_volume(jcr, jcr->db, 1, mr)) {
       jcr->MediaId = mr->MediaId;
       Dmsg1(20, "Find_next_vol MediaId=%d\n", jcr->MediaId);
-      strcpy(jcr->VolumeName, mr->VolumeName);
+      pm_strcpy(&jcr->VolumeName, mr->VolumeName);
       return 1;
    }
    return 0;
    POOLMEM *query = get_pool_memory(PM_EMSG);
    char *select =
           "SELECT MediaId, LastWritten FROM Media "
-          "WHERE PoolId=%d AND Recycle=1 AND VolStatus=\"Purged\" "
+          "WHERE PoolId=%u AND Recycle=1 AND VolStatus=\"Purged\" "
           "AND MediaType=\"%s\"";
 
    Dmsg0(100, "Enter recycle_oldest_purged_volume\n");