Example #1
0
/*
 *   Purge records from database
 *
 *     Purge Files (from) [Job|JobId|Client|Volume]
 *     Purge Jobs  (from) [Client|Volume]
 *
 *  N.B. Not all above is implemented yet.
 */
int purgecmd(UAContext *ua, const char *cmd)
{
   int i;
   CLIENTRES *client;
   MEDIA_DBR mr;
   JOB_DBR  jr;
   static const char *keywords[] = {
      NT_("files"),
      NT_("jobs"),
      NT_("volume"),
      NT_("quota"),
      NULL
   };

   static const char *files_keywords[] = {
      NT_("Job"),
      NT_("JobId"),
      NT_("Client"),
      NT_("Volume"),
      NULL
   };

   static const char *quota_keywords[] = {
      NT_("Client"),
      NULL
   };

   static const char *jobs_keywords[] = {
      NT_("Client"),
      NT_("Volume"),
      NULL
   };

   ua->warning_msg(_(
      "\nThis command can be DANGEROUS!!!\n\n"
      "It purges (deletes) all Files from a Job,\n"
      "JobId, Client or Volume; or it purges (deletes)\n"
      "all Jobs from a Client or Volume without regard\n"
      "to retention periods. Normally you should use the\n"
      "PRUNE command, which respects retention periods.\n"));

   if (!open_db(ua)) {
      return 1;
   }
   switch (find_arg_keyword(ua, keywords)) {
   /* Files */
   case 0:
      switch(find_arg_keyword(ua, files_keywords)) {
      case 0:                         /* Job */
      case 1:                         /* JobId */
         if (get_job_dbr(ua, &jr)) {
            char jobid[50];
            edit_int64(jr.JobId, jobid);
            purge_files_from_jobs(ua, jobid);
         }
         return 1;
      case 2:                         /* client */
         client = get_client_resource(ua);
         if (client) {
            purge_files_from_client(ua, client);
         }
         return 1;
      case 3:                         /* Volume */
         if (select_media_dbr(ua, &mr)) {
            purge_files_from_volume(ua, &mr);
         }
         return 1;
      }
   /* Jobs */
   case 1:
      switch(find_arg_keyword(ua, jobs_keywords)) {
      case 0:                         /* client */
         client = get_client_resource(ua);
         if (client) {
            purge_jobs_from_client(ua, client);
         }
         return 1;
      case 1:                         /* Volume */
         if (select_media_dbr(ua, &mr)) {
            purge_jobs_from_volume(ua, &mr, /*force*/true);
         }
         return 1;
      }
   /* Volume */
   case 2:
      /* Perform ActionOnPurge (action=truncate) */
      if (find_arg(ua, "action") >= 0) {
         return action_on_purge_cmd(ua, ua->cmd);
      }

      while ((i=find_arg(ua, NT_("volume"))) >= 0) {
         if (select_media_dbr(ua, &mr)) {
            purge_jobs_from_volume(ua, &mr, /*force*/true);
         }
         *ua->argk[i] = 0;            /* zap keyword already seen */
         ua->send_msg("\n");
      }
      return 1;
   /* Quota */
   case 3:
      switch(find_arg_keyword(ua, quota_keywords)) {
      case 0:                         /* client */
         client = get_client_resource(ua);
         if (client) {
            purge_quota_from_client(ua, client);
         }
         return 1;
      }
   default:
      break;
   }
   switch (do_keyword_prompt(ua, _("Choose item to purge"), keywords)) {
   case 0:                            /* files */
      client = get_client_resource(ua);
      if (client) {
         purge_files_from_client(ua, client);
      }
      break;
   case 1:                            /* jobs */
      client = get_client_resource(ua);
      if (client) {
         purge_jobs_from_client(ua, client);
      }
      break;
   case 2:                            /* Volume */
      if (select_media_dbr(ua, &mr)) {
         purge_jobs_from_volume(ua, &mr, /*force*/true);
      }
      break;
   case 3:
      client = get_client_resource(ua); /* Quota */
      if (client) {
         purge_quota_from_client(ua, client);
      }
   }
   return 1;
}
Example #2
0
/*
 *  Items needed:
 *   mr.PoolId must be set
 *   mr.StorageId should also be set
 *   mr.ScratchPoolId could be set (used if create==true)
 *   jcr->wstore
 *   jcr->db
 *   jcr->pool
 *   MEDIA_DBR mr with PoolId set
 *   create -- whether or not to create a new volume
 */
int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index,             
                                bool create, bool prune)
{
   int retry = 0;
   bool ok;
   bool InChanger;
   STORE *store = jcr->wstore;

   bstrncpy(mr->MediaType, store->media_type, sizeof(mr->MediaType));
   Dmsg3(100, "find_next_vol_for_append: JobId=%u PoolId=%d, MediaType=%s\n", 
         (uint32_t)jcr->JobId, (int)mr->PoolId, mr->MediaType);
   /*
    * If we are using an Autochanger, restrict Volume
    *   search to the Autochanger on the first pass
    */
   InChanger = store->autochanger;
   /*
    * Find the Next Volume for Append
    */
   db_lock(jcr->db);
   for ( ;; ) {
      bstrncpy(mr->VolStatus, "Append", sizeof(mr->VolStatus));  /* want only appendable volumes */
      /*
       *  1. Look for volume with "Append" status.
       */
      ok = db_find_next_volume(jcr, jcr->db, index, InChanger, mr);

      if (!ok) {
         Dmsg4(150, "after find_next_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
               ok, index, InChanger, mr->VolStatus);
         /*
          * 2. Try finding a recycled volume
          */
         ok = find_recycled_volume(jcr, InChanger, mr);
         Dmsg2(150, "find_recycled_volume ok=%d FW=%d\n", ok, mr->FirstWritten);
         if (!ok) {
            /*
             * 3. Try recycling any purged volume
             */
            ok = recycle_oldest_purged_volume(jcr, InChanger, mr);
            if (!ok) {
               /*
                * 4. Try pruning Volumes
                */
               if (prune) {
                  Dmsg0(150, "Call prune_volumes\n");
                  prune_volumes(jcr, InChanger, mr);
               }
               ok = recycle_oldest_purged_volume(jcr, InChanger, mr);
               if (!ok && create) {
                  Dmsg4(150, "after prune volumes_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
                        ok, index, InChanger, mr->VolStatus);
                  /*
                   * 5. Try pulling a volume from the Scratch pool
                   */ 
                  ok = get_scratch_volume(jcr, InChanger, mr);
                  Dmsg4(150, "after get scratch volume ok=%d index=%d InChanger=%d Vstat=%s\n",
                        ok, index, InChanger, mr->VolStatus);
               }
               /*
                * If we are using an Autochanger and have not found
                * a volume, retry looking for any volume. 
                */
               if (!ok && InChanger) {
                  InChanger = false;
                  continue;           /* retry again accepting any volume */
               }
            }
         }


         if (!ok && create) {
            /*
             * 6. Try "creating" a new Volume
             */
            ok = newVolume(jcr, mr);
         }
         /*
          *  Look at more drastic ways to find an Appendable Volume
          */
         if (!ok && (jcr->pool->purge_oldest_volume ||
                     jcr->pool->recycle_oldest_volume)) {
            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(200, "Find oldest=%d Volume\n", ok);
            if (ok && prune) {
               UAContext *ua;
               Dmsg0(200, "Try purge Volume.\n");
               /*
                * 7.  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);
                  ok = purge_jobs_from_volume(ua, mr);
               /*
                * 8. 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);
                  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);
               }
            }
         }
      }
      Dmsg2(100, "VolJobs=%d FirstWritten=%d\n", mr->VolJobs, mr->FirstWritten);
      if (ok) {
         /* If we can use the volume, check if it is expired */
         if (has_volume_expired(jcr, mr)) {
            if (retry++ < 200) {            /* sanity check */
               continue;                    /* try again from the top */
            } else {
               Jmsg(jcr, M_ERROR, 0, _(
"We seem to be looping trying to find the next volume. I give up.\n"));
            }
         }
      }
      break;
   } /* end for loop */
   db_unlock(jcr->db);
   Dmsg1(150, "return ok=%d find_next_vol\n", ok);
   return ok;
}