void
rar_check_multi_vomule (FrCommand *comm)
{
	GFile *file;
	char   buffer[11];

	file = g_file_new_for_path (comm->filename);
	if (! g_load_file_in_buffer (file, buffer, 11, NULL)) {
		g_object_unref (file);
		return;
	}

	if (memcmp (buffer, "Rar!", 4) != 0)
		return;

	if ((buffer[10] & 0x01) == 0x01) {
		char   *volume_name = NULL;
		char   *name;

		name = g_filename_to_utf8 (file_name_from_path (comm->filename), -1, NULL, NULL, NULL);

		volume_name = get_first_volume_name (name, "^(.*\\.part)([0-9]+)(\\.rar)$", FIRST_VOLUME_IS_001);
		if (volume_name == NULL)
			volume_name = get_first_volume_name (name, "^(.*\\.r)([0-9]+)$", FIRST_VOLUME_IS_RAR);
		if (volume_name == NULL)
			volume_name = get_first_volume_name (name, "^(.*\\.)([0-9]+)$", FIRST_VOLUME_IS_001);

		if (volume_name != NULL) {
			GFile *parent;
			GFile *child;
			char  *volume_filename;

			parent = g_file_get_parent (file);
			child = g_file_get_child (parent, volume_name);
			volume_filename = g_file_get_path (child);
			fr_command_set_multi_volume (comm, volume_filename);

			g_free (volume_filename);
			g_object_unref (child);
			g_object_unref (parent);
		}

		g_free (name);
	}

	g_object_unref (file);
}
示例#2
0
/** controlling daemon main loop */
static int
main_loop(struct program_params *pp)
{
    int ret;

    const char *lv_name = get_first_volume_name(pp);

    while (!stop) {

        // if move daemon is working, wait 5 minutes, start from beginning
        switch(move_daemon_status(pp, lv_name)) {
          case PVMOVE_WORKING:
            sleep(get_pvwait(pp, lv_name));
            continue;
            break;
          case PVMOVE_IDLE:
            break; /* do nothing, continue */
          default:
            fprintf(stderr, "Unknown response from move_daemon_status()\n");
            goto no_cleanup;
            break;
        }

        // refresh stats, read new stats from file
        struct extent_stats *es = NULL;
        ret = get_volume_stats(pp, lv_name, &es);
        if (ret) {
            fprintf(stderr, "get_extent_stats error\n");
            break;
        }

        // get most used min(100,free_space) extents (read and write multipliers from
        // config file), check if they're on fast or slow storage
        // move hot extents from slow storage, queue the move in move daemon
        // continue if move queued
        for (int tier=0; tier<TIER_MAX; tier++) {

            if (!lower_tiers_exist(pp, lv_name, tier))
                break;

            off_t free_space = get_avaiable_space(pp, lv_name, tier);
            if (free_space < 0) {
                fprintf(stderr, "get_free_space error\n");
                goto no_cleanup;
            }

            if (free_space == 0)
                continue;

            // always leave 5 extents worth of free space so that we always
            // can move cold extents from higher tier
            off_t available_extents = free_space
                / get_extent_size(pp, lv_name) - 5;
            if (available_extents < 0)
              available_extents = 0;

            struct extents *ext = NULL;

            // get next hottest min(100, free_space) extents
            size_t max_extents = 100;
            if (max_extents > available_extents)
                max_extents = available_extents;

            ret = extents_selector(es, &ext, pp, lv_name, tier, max_extents, ES_HOT);
            if (ret) {
                fprintf(stderr, "extents_selector error\n");
                goto no_cleanup;
            }

            if (!ext->length) {
                free_extents(ext);
                continue;
            }

            printf("Moving extents to higher tier\n");

            // move them from slow storage,
            // until no space left
            ret = queue_extents_move(ext, pp, lv_name, tier);
            if (ret) {
                fprintf(stderr, "Can't queue extents move\n");
                goto no_cleanup;
            }

            free_extents(ext);

            if (!stop)
                sleep(get_pvwait(pp, lv_name));

            // continue main loop, free memory before
            goto cont;
        }

        printf("All high tiers full\n");

        // pin extents to their current physical volumes, this will cause them
        // to be moved only when the temperature difference is large
        ret = add_pinning_scores(es, pp, lv_name);
        if (ret) {
            fprintf(stderr, "can't add pining scores\n");
            goto no_cleanup;
        }

        // If there are blocks in slow storage with higher
        // score than ones in fast storage, move 10 worst extents from fast to slow
        // if move queued, continue
        struct extents *prev_tier_max = NULL;
        int prev_tier = -1;
        for (int tier = TIER_MAX; tier >= 0; tier--) {
            off_t free_space = get_avaiable_space(pp, lv_name, tier);
            if (free_space < 0) {
                fprintf(stderr, "get_avaiable_space error\n");
                goto no_cleanup;
            }

            if (!free_space) {
                if (higher_tiers_exist(pp, lv_name, tier))
                    continue;
                else
                    break;
            }

            struct extents *curr_tier_min = NULL;

            printf("trying to move cold extents from tier %i\n", tier);

            if (!prev_tier_max) { // get base line extents
                ret = extents_selector(es, &prev_tier_max, pp, lv_name, tier-1,
                    5, ES_HOT);
                if (ret) {
                    fprintf(stderr, "extent_selector error\n");
                    goto no_cleanup;
                }
                prev_tier = tier;
                continue;
            }

            ret = extents_selector(es, &curr_tier_min, pp, lv_name, tier, 5, ES_COLD);
            if (ret) {
                fprintf(stderr, "%s:%i: extent_selector error\n", __FILE__, __LINE__);
                goto no_cleanup;
            }

            printf("low tier best: %f\n", prev_tier_max->extents[0]->score);
            printf("high tier worst: %f\n", curr_tier_min->extents[0]->score);

            // check if extents in lower tier are hotter
            if (compare_extents(prev_tier_max, curr_tier_min) > 0) {
                float prev_score = get_extent_score(get_extent(prev_tier_max, 0));
                float curr_score = get_extent_score(get_extent(curr_tier_min, 0));
                // don't move more extents that would push very hot extents
                // to low tier or cold extents to higher tier when there is
                // more cold extents to swap than hotter and vice-versa
                int prev_count = count_extents(prev_tier_max, curr_score, ES_COLD);
                int curr_count = count_extents(curr_tier_min, prev_score, ES_HOT);

                int move_extents =
                  (prev_count > curr_count)?curr_count:prev_count;

                truncate_extents(prev_tier_max, move_extents);
                truncate_extents(curr_tier_min, move_extents);

                // queue move of extents that remain
                ret = queue_extents_move(prev_tier_max, pp, lv_name, tier);
                if (ret) {
                    fprintf(stderr, "%s:%i: queue extents failed\n", __FILE__, __LINE__);
                    goto no_cleanup;
                }
                ret = queue_extents_move(curr_tier_min, pp, lv_name, prev_tier);
                if (ret) {
                    fprintf(stderr, "%s:%i: queue extents failed\n", __FILE__, __LINE__);
                    goto no_cleanup;
                }
            } else {
                printf("Nothing to do\n");
            }

            free_extents(curr_tier_min);
            free_extents(prev_tier_max);
            prev_tier_max = NULL;

            // remember previous tier extents
            ret = extents_selector(es, &prev_tier_max, pp, lv_name, tier, 5, ES_HOT);
            if (ret) {
                fprintf(stderr, "%s:%i: Extent_selector error\n", __FILE__, __LINE__);
                goto no_cleanup;
            }
            prev_tier = tier;
        }

        // wait 10 minutes
        if (!stop)
            sleep(get_check_wait(pp, lv_name));

cont:
        free_extent_stats(es);
    }

no_cleanup:

    if (stop)
        return 0;
    else
        return 1;
}
示例#3
0
int
main(int argc, char **argv) {
	int ret = 0;
	struct activity_stats *activ = NULL;
	struct thread_param *tp = malloc(sizeof(struct thread_param));
	assert(tp);

	struct lvmtscd_params pp = { 0 };

	if (parse_arguments(argc, argv, &pp)) {
		free(tp);
		return 1;
	}

    pp.pp = new_program_params();
    if(!pp.pp) {
        fprintf(stderr, "Out of memory error\n");
        exit(1);
    }

    free(pp.pp->conf_file_path);
    pp.pp->conf_file_path = pp.config_file;

    ret = read_config(pp.pp);
    if(ret) {
        free_program_params(pp.pp);
        exit(1);
    }

    const char *vol_name = get_first_volume_name(pp.pp);

    if(!pp.lv_dev_name)
      asprintf(&pp.lv_dev_name, "/dev/%s/%s", get_volume_vg(pp.pp, vol_name),
          get_volume_lv(pp.pp, vol_name));

	//activ = new_activity_stats_s(1<<10); // assume 2^11 extents (40GiB)
	if(read_activity_stats(&activ, pp.file)) {
		fprintf(stderr, "Can't read \"%s\". Ignoring.\n", pp.file);
		activ = new_activity_stats_s(1<<10); // assume 2^11 extents (40GiB)
	}

	if (pp.daemonize)
		daemonize();

	signal(SIGINT, signalHandler);
	signal(SIGTERM, signalHandler);
	signal(SIGHUP, ignoreHandler);

	tp->activ = activ;
	tp->delay = pp.delay;
	tp->file = pp.file;
	tp->ender = &programEnd;

	pthread_attr_t pt_attr;
	pthread_t thread;

	if (pthread_attr_init(&pt_attr)) {
		fprintf(stderr, "Can't initialize thread attribute\n");
		return 1;
	}

	if(pthread_create(&thread, &pt_attr, &disk_write_worker, tp)) {
		fprintf(stderr, "Can't create thread\n");
		return 1;
	}

	if (collect_trace_points(pp.lv_dev_name,
				 activ,
				 pp.granularity,
				 pp.esize,
				 &programEnd)) {
		fprintf(stderr, "Error while tracing");
		ret = 1;
	}

	fprintf(stderr, "Writing activity stats...");

	union sigval sigArg = {.sival_int=0};
	pthread_sigqueue(thread, SIGHUP, sigArg);

	void *thret;
	pthread_join(thread, &thret);

	destroy_activity_stats(activ);
    free_program_params(pp.pp);

	fprintf(stderr, "done\n");

	return ret;
}