Example #1
0
  /* Calculates approximation of the percentile of the original distribution
   * The quality of the value depends on how much information was lost when creating the histogram
   * Inside a bucket, we use linear interpolation
   */
  double percentile( double p )
  {
    assert( p >= 0.0 && p <= 1.0 && "p must be within [0.0 1.0]" );
    if ( !num_entries() )
      return 0.0;

    size_t target = static_cast<size_t>( p * num_entries() );

    // Performance Optimization: We assume a roughly balanced distribution,
    // so for p <= 0.5 we start from min counting upwards, otherwise from max counting downwards
    if ( p <= 0.5 )
    {
      size_t count = 0;
      for ( size_t i = 0, size = data().size(); i < size; ++i )
      {
        count += data()[ i ];
        if ( count >= target )
        {
          // We reached the target bucket.

          // Calculate linear interpolation x
          double x = data()[ i ] ? ( count - target ) / data()[ i ] : 0.0;
          assert( x >= 0.0 && x <= 1.0 );

          // Return result
          return _min + ( i + x ) * bucket_size();
        }
      }
    }
    else
    {
      size_t count = num_entries();
      for ( int i = static_cast< int >( data().size() ) - 1; i >= 0; --i )
      {
        count -= data()[ i ];
        if ( count <= target )
        {
          // We reached the target bucket.

          // Calculate linear interpolation x
          double x = data()[ i ] ? ( target - count ) / data()[ i ] : 0.0;
          assert( x >= 0.0 && x <= 1.0 );

          // Return result
          return _max - ( i - x ) * bucket_size();
        }
      }
    }

    assert( false ); return 0.0;
  }
Example #2
0
/*
 * Build the list of tapes we'll be wanting, and include data about the
 * files we want from said tapes while we're at it (the whole find_result
 * should do fine)
 */
tapelist_t *
list_needed_tapes(
    GSList *	dumpspecs,
    int		only_one,
    disklist_t	*diskqp)
{
    GSList *needed_tapes = NULL;
    GSList *seen_dumps = NULL;
    GSList *iter, *iter2;
    find_result_t *alldumps = NULL;
    find_result_t *curmatch = NULL;
    find_result_t *matches = NULL;
    tapelist_t *tapes = NULL;
    int usage_order_counter = 0;
    char *conf_tapelist;

    /* Load the tape list */
    conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST));
    if(read_tapelist(conf_tapelist)) {
        error(_("could not load tapelist \"%s\""), conf_tapelist);
	/*NOTREACHED*/
    }
    amfree(conf_tapelist);

    /* Grab a find_output_t of all logged dumps */
    alldumps = find_dump(diskqp);
    if(alldumps == NULL){
        g_fprintf(stderr, _("No dump records found\n"));
	dbclose();
        exit(1);
    }

    /* Compare all known dumps to our match list, note what we'll need */
    matches = dumps_match_dumpspecs(alldumps, dumpspecs, 1);

    /* D = dump_timestamp, newest first
     * h = hostname
     * k = diskname
     * l = level
     * p = partnum
     * w = write_timestamp */
    sort_find_result("Dhklpw", &matches);

    for(curmatch = matches; curmatch; curmatch = curmatch->next) {
	int havetape = 0;

	/* keep only first dump if only_one */
	if (only_one &&
	    curmatch != matches &&
	    (strcmp(curmatch->hostname, matches->hostname) ||
	     strcmp(curmatch->diskname, matches->diskname) ||
	     strcmp(curmatch->timestamp, matches->timestamp) ||
	     curmatch->level != matches->level)) {
	    continue;
	}
	if(strcmp("OK", curmatch->status)){
	    g_fprintf(stderr,_("Dump %s %s %s %d had status '%s', skipping\n"),
		             curmatch->timestamp, curmatch->hostname,
			     curmatch->diskname, curmatch->level,
			     curmatch->status);
	    continue;
	}

	for(iter = needed_tapes; iter; iter = iter->next) {
	    needed_tape_t *curtape = iter->data;
	    if (!strcmp(curtape->label, curmatch->label)) {
		int keep = 1;

		havetape = 1;

		for(iter2 = curtape->files; iter2; iter2 = iter2->next){
		    find_result_t *rsttemp = iter2->data;
		    if(curmatch->filenum == rsttemp->filenum){
			g_fprintf(stderr, _("Seeing multiple entries for tape "
				   "%s file %lld, using most recent\n"),
				    curtape->label,
				    (long long)curmatch->filenum);
			keep = 0;
		    }
		}
		if(!keep){
		    break;
		}

		curtape->isafile = (curmatch->filenum < 1);
		curtape->files = g_slist_prepend(curtape->files, curmatch);
		break;
	    }
	}
	if (!havetape) {
	    needed_tape_t *newtape = g_new0(needed_tape_t, 1);
	    newtape->usage_order = usage_order_counter++;
	    newtape->files = g_slist_prepend(newtape->files, curmatch);
	    newtape->isafile = (curmatch->filenum < 1);
	    newtape->label = curmatch->label;
	    needed_tapes = g_slist_prepend(needed_tapes, newtape);
	} /* if(!havetape) */

    } /* for(curmatch = matches ... */

    if(g_slist_length(needed_tapes) == 0){
      g_fprintf(stderr, _("No matching dumps found\n"));
      exit(1);
      /* NOTREACHED */
    }

    /* sort the tapelist by tape write_timestamp */
    needed_tapes = g_slist_sort(needed_tapes, sort_needed_tapes_by_write_timestamp);

    /* stick that list in a structure that librestore will understand, removing
     * files we have already seen in the process; this prefers the earliest written
     * copy of any dumps which are available on multiple tapes */
    seen_dumps = NULL;
    for(iter = needed_tapes; iter; iter = iter->next) {
	needed_tape_t *curtape = iter->data;
	for(iter2 = curtape->files; iter2; iter2 = iter2->next) {
	    find_result_t *curfind = iter2->data;
	    find_result_t *prev;
	    GSList *iter;
	    int have_part;

	    /* have we already seen this? */
	    have_part = 0;
	    for (iter = seen_dumps; iter; iter = iter->next) {
		prev = iter->data;

		if (!strcmp(prev->partnum, curfind->partnum) &&
		    !strcmp(prev->hostname, curfind->hostname) &&
		    !strcmp(prev->diskname, curfind->diskname) &&
		    !strcmp(prev->timestamp, curfind->timestamp) &&
		    prev->level == curfind->level) {
		    have_part = 1;
		    break;
		}
	    }

	    if (!have_part) {
		seen_dumps = g_slist_prepend(seen_dumps, curfind);
		tapes = append_to_tapelist(tapes, curtape->label,
					   curfind->filenum, -1, curtape->isafile);
	    }
	}
    }

    /* free our resources */
    for (iter = needed_tapes; iter; iter = iter->next) {
	needed_tape_t *curtape = iter->data;
	g_slist_free(curtape->files);
	g_free(curtape);
    }
    g_slist_free(seen_dumps);
    g_slist_free(needed_tapes);
    free_find_result(&matches);

    /* and we're done */
    g_fprintf(stderr, _("%d tape(s) needed for restoration\n"), num_entries(tapes));
    return(tapes);
}