Beispiel #1
0
static void* read_recipe_thread(void *arg) {

	int i, j, k;
	for (i = 0; i < jcr.bv->number_of_files; i++) {
		TIMER_DECLARE(1);
		TIMER_BEGIN(1);

		struct recipeMeta *r = read_next_recipe_meta(jcr.bv);

		struct chunk *c = new_chunk(sdslen(r->filename) + 1);
		strcpy(c->data, r->filename);
		SET_CHUNK(c, CHUNK_FILE_START);

		TIMER_END(1, jcr.read_recipe_time);

		sync_queue_push(restore_recipe_queue, c);

		jcr.file_num++;

		for (j = 0; j < r->chunknum; j++) {
			TIMER_DECLARE(1);
			TIMER_BEGIN(1);

			struct chunkPointer* cp = read_next_n_chunk_pointers(jcr.bv, 1, &k);

			struct chunk* c = new_chunk(0);
			memcpy(&c->fp, &cp->fp, sizeof(fingerprint));
			c->size = cp->size;
			c->id = cp->id;

			TIMER_END(1, jcr.read_recipe_time);
			jcr.data_size += c->size;
			jcr.chunk_num++;

			sync_queue_push(restore_recipe_queue, c);
			free(cp);
		}

		c = new_chunk(0);
		SET_CHUNK(c, CHUNK_FILE_END);
		sync_queue_push(restore_recipe_queue, c);

		free_recipe_meta(r);
	}

	sync_queue_term(restore_recipe_queue);
	return NULL;
}
Beispiel #2
0
static void* sha1_thread(void* arg) {
	char code[41];
	while (1) {
		struct chunk* c = sync_queue_pop(chunk_queue);

		if (c == NULL) {
			sync_queue_term(hash_queue);
			break;
		}

		if (CHECK_CHUNK(c, CHUNK_FILE_START) || CHECK_CHUNK(c, CHUNK_FILE_END)) {
			sync_queue_push(hash_queue, c);
			continue;
		}

		TIMER_DECLARE(1);
		TIMER_BEGIN(1);
		SHA_CTX ctx;
		SHA_Init(&ctx);
		SHA_Update(&ctx, c->data, c->size);
		SHA_Final(c->fp, &ctx);
		TIMER_END(1, jcr.hash_time);

		hash2code(c->fp, code);
		code[40] = 0;
		VERBOSE("Hash phase: %ldth chunk identified by %s", chunk_num++, code);

		sync_queue_push(hash_queue, c);
	}
	return NULL;
}
Beispiel #3
0
static void* lru_restore_thread(void *arg) {
	struct lruCache *cache;
	if (destor.simulation_level >= SIMULATION_RESTORE)
		cache = new_lru_cache(destor.restore_cache[1], free_container_meta,
				lookup_fingerprint_in_container_meta);
	else
		cache = new_lru_cache(destor.restore_cache[1], free_container,
				lookup_fingerprint_in_container);

	struct chunk* c;
	while ((c = sync_queue_pop(restore_recipe_queue))) {

		if (CHECK_CHUNK(c, CHUNK_FILE_START) || CHECK_CHUNK(c, CHUNK_FILE_END)) {
			sync_queue_push(restore_chunk_queue, c);
			continue;
		}

		TIMER_DECLARE(1);
		TIMER_BEGIN(1);

		if (destor.simulation_level >= SIMULATION_RESTORE) {
			struct containerMeta *cm = lru_cache_lookup(cache, &c->fp);
			if (!cm) {
				VERBOSE("Restore cache: container %lld is missed", c->id);
				cm = retrieve_container_meta_by_id(c->id);
				assert(lookup_fingerprint_in_container_meta(cm, &c->fp));
				lru_cache_insert(cache, cm, NULL, NULL);
				jcr.read_container_num++;
			}

			TIMER_END(1, jcr.read_chunk_time);
		} else {
			struct container *con = lru_cache_lookup(cache, &c->fp);
			if (!con) {
				VERBOSE("Restore cache: container %lld is missed", c->id);
				con = retrieve_container_by_id(c->id);
				lru_cache_insert(cache, con, NULL, NULL);
				jcr.read_container_num++;
			}
			struct chunk *rc = get_chunk_in_container(con, &c->fp);
			assert(rc);
			TIMER_END(1, jcr.read_chunk_time);
			sync_queue_push(restore_chunk_queue, rc);
		}

		free_chunk(c);
	}

	sync_queue_term(restore_chunk_queue);

	free_lru_cache(cache);

	return NULL;
}
Beispiel #4
0
/*
 * We must ensure a container is either in the buffer or written to disks.
 */
static void* append_thread(void *arg) {

	while (1) {
		struct container *c = sync_queue_get_top(container_buffer);
		if (c == NULL)
			break;

		TIMER_DECLARE(1);
		TIMER_BEGIN(1);

		write_container(c);

		TIMER_END(1, jcr.write_time);

		sync_queue_pop(container_buffer);

		free_container(c);
	}

	return NULL;
}
Beispiel #5
0
void har_monitor_update(containerid id, int32_t size) {
	TIMER_DECLARE(1);
	TIMER_BEGIN(1);
	struct containerRecord* record = g_hash_table_lookup(
			container_utilization_monitor, &id);
	if (record) {
		record->size += size;
	} else {

		record = (struct containerRecord*) malloc(
					sizeof(struct containerRecord));
		record->cid = id;
		record->size = 0;
		g_hash_table_insert(container_utilization_monitor,
				&record->cid, record);

		record->size += size;

	}
	TIMER_END(1, jcr.rewrite_time);
}
Beispiel #6
0
static void* read_trace_thread(void *argv) {

	FILE *trace_file = fopen(jcr.path, "r");
	char line[128];

	while (1) {
		TIMER_DECLARE(1);
		TIMER_BEGIN(1);
		fgets(line, 128, trace_file);
		TIMER_END(1, jcr.read_time);

		if (strcmp(line, "stream end") == 0) {
			sync_queue_term(trace_queue);
			break;
		}

		struct chunk* c;

		TIMER_BEGIN(1),

		assert(strncmp(line, "file start ", 11) == 0);
		int filenamelen;
		sscanf(line, "file start %d", &filenamelen);

		/* An additional '\n' is read */
		c = new_chunk(filenamelen + 2);
		fgets(c->data, filenamelen + 2, trace_file);
		c->data[filenamelen] = 0;
		VERBOSE("Reading: %s", c->data);

		SET_CHUNK(c, CHUNK_FILE_START);

		TIMER_END(1, jcr.read_time);

		sync_queue_push(trace_queue, c);

		TIMER_BEGIN(1);
		fgets(line, 128, trace_file);
		while (strncmp(line, "file end", 8) != 0) {
			c = new_chunk(0);

			char code[41];
			strncpy(code, line, 40);
			code2hash(code, c->fp);

			c->size = atoi(line + 41);
			jcr.chunk_num++;
			jcr.data_size += c->size;

			TIMER_END(1, jcr.read_time);
			sync_queue_push(trace_queue, c);
			TIMER_BEGIN(1),

			fgets(line, 128, trace_file);
		}

		c = new_chunk(0);
		SET_CHUNK(c, CHUNK_FILE_END);
		sync_queue_push(trace_queue, c);

		jcr.file_num++;
	}

	fclose(trace_file);
	return NULL;
}
Beispiel #7
0
void do_backup(char *path) {

	init_recipe_store();
	init_container_store();
	init_index();

	init_backup_jcr(path);
    
	NOTICE("\n\n==== backup begin ====");

	TIMER_DECLARE(1);
	TIMER_BEGIN(1);

    time_t start = time(NULL);
	if (destor.simulation_level == SIMULATION_ALL) {
		start_read_trace_phase();
	} else {
		start_read_phase();
		start_chunk_phase();
		start_hash_phase();
	}
	start_dedup_phase();
	start_rewrite_phase();
	start_filter_phase();

    do{
        sleep(5);
        /*time_t now = time(NULL);*/
        fprintf(stderr,"job %" PRId32 ", data size %" PRId64 " bytes, %" PRId32 " chunks, %d files processed\r",
                jcr.id, jcr.data_size, jcr.chunk_num, jcr.file_num);
    }while(jcr.status == JCR_STATUS_RUNNING || jcr.status != JCR_STATUS_DONE);
    fprintf(stderr,"job %" PRId32 ", data size %" PRId64 " bytes, %" PRId32 " chunks, %d files processed\n",
        jcr.id, jcr.data_size, jcr.chunk_num, jcr.file_num);

	if (destor.simulation_level == SIMULATION_ALL) {
		stop_read_trace_phase();
	} else {
		stop_read_phase();
		stop_chunk_phase();
		stop_hash_phase();
	}
	stop_dedup_phase();
	stop_rewrite_phase();
	stop_filter_phase();

	TIMER_END(1, jcr.total_time);
    
	close_index();
	close_container_store();
	close_recipe_store();

	update_backup_version(jcr.bv);
	free_backup_version(jcr.bv);
    
    
	printf("\n\njob id: %" PRId32 "\n", jcr.id);
    printf("index method: %d.(Remark 0: NO; 1: DDFS; 2: Extreme binning; 3: Silo; 4: Sparse; 5: Sampled; 6: Block; 7: Learn)\n",
           destor.index_specific);
    
    printf("sampling method: %d (%d) (Remark 1:Random; 2: Min; 3: Uniform; 4: Optimized_min)\n", destor.index_sampling_method[0], destor.index_sampling_method[1]);
	printf("segment method: %d (%d) (Remark 0: Fixed; 1: Content; 2: File)\n", destor.index_segment_algorithm[0], destor.index_segment_algorithm[1]);
    printf("prefetch # of segments: %d (Remark 1 for sparse index)\n", destor.index_segment_prefech);
    printf("segment selection method: %d (%d)(Remark 0: Base; 1: Top; 2: Mix)\n", destor.index_segment_selection_method[0], destor.index_segment_selection_method[1]);
    printf("backup path: %s\n", jcr.path);
	printf("number of files: %d\n", jcr.file_num);
	printf("number of chunks: %" PRId32 " (%" PRId64 " bytes on average)\n", jcr.chunk_num,
			jcr.data_size / jcr.chunk_num);
	printf("number of unique chunks: %" PRId32 "\n", jcr.unique_chunk_num);
	printf("total size(B): %" PRId64 "\n", jcr.data_size);
	printf("stored data size(B): %" PRId64 "\n",
			jcr.unique_data_size + jcr.rewritten_chunk_size);
	printf("deduplication ratio: %.4f, %.4f\n",
			jcr.data_size != 0 ?
					(jcr.data_size - jcr.unique_data_size
							- jcr.rewritten_chunk_size)
							/ (double) (jcr.data_size) :
					0,
			jcr.data_size
					/ (double) (jcr.unique_data_size + jcr.rewritten_chunk_size));
	printf("total time(s): %.3f\n", jcr.total_time / 1000000);
    printf("the index memory footprint (B): %" PRId32 "\n", destor.index_memory_footprint);
	printf("throughput(MB/s): %.2f\n",
			(double) jcr.data_size * 1000000 / (1024 * 1024 * jcr.total_time));
	printf("number of zero chunks: %" PRId32 "\n", jcr.zero_chunk_num);
	printf("size of zero chunks: %" PRId64 "\n", jcr.zero_chunk_size);
	printf("number of rewritten chunks: %" PRId32 "\n", jcr.rewritten_chunk_num);
	printf("size of rewritten chunks: %" PRId64 "\n", jcr.rewritten_chunk_size);
	printf("rewritten rate in size: %.3f\n",
			jcr.rewritten_chunk_size / (double) jcr.data_size);

	destor.data_size += jcr.data_size;
	destor.stored_data_size += jcr.unique_data_size + jcr.rewritten_chunk_size;

	destor.chunk_num += jcr.chunk_num;
	destor.stored_chunk_num += jcr.unique_chunk_num + jcr.rewritten_chunk_num;
	destor.zero_chunk_num += jcr.zero_chunk_num;
	destor.zero_chunk_size += jcr.zero_chunk_size;
	destor.rewritten_chunk_num += jcr.rewritten_chunk_num;
	destor.rewritten_chunk_size += jcr.rewritten_chunk_size;

	printf("read_time : %.3fs, %.2fMB/s\n", jcr.read_time / 1000000,
			jcr.data_size * 1000000 / jcr.read_time / 1024 / 1024);
	printf("chunk_time : %.3fs, %.2fMB/s\n", jcr.chunk_time / 1000000,
			jcr.data_size * 1000000 / jcr.chunk_time / 1024 / 1024);
	printf("hash_time : %.3fs, %.2fMB/s\n", jcr.hash_time / 1000000,
			jcr.data_size * 1000000 / jcr.hash_time / 1024 / 1024);

	printf("dedup_time : %.3fs, %.2fMB/s\n",
			jcr.dedup_time / 1000000,
			jcr.data_size * 1000000 / jcr.dedup_time / 1024 / 1024);

	printf("rewrite_time : %.3fs, %.2fMB/s\n", jcr.rewrite_time / 1000000,
			jcr.data_size * 1000000 / jcr.rewrite_time / 1024 / 1024);

	printf("filter_time : %.3fs, %.2fMB/s\n",
			jcr.filter_time / 1000000,
			jcr.data_size * 1000000 / jcr.filter_time / 1024 / 1024);

	printf("write_time : %.3fs, %.2fMB/s\n", jcr.write_time / 1000000,
			jcr.data_size * 1000000 / jcr.write_time / 1024 / 1024);

	//double seek_time = 0.005; //5ms
	//double bandwidth = 120 * 1024 * 1024; //120MB/s

	/*	double index_lookup_throughput = jcr.data_size
	 / (index_read_times * seek_time
	 + index_read_entry_counter * 24 / bandwidth) / 1024 / 1024;

	 double write_data_throughput = 1.0 * jcr.data_size * bandwidth
	 / (jcr->unique_chunk_num) / 1024 / 1024;
	 double index_read_throughput = 1.0 * jcr.data_size / 1024 / 1024
	 / (index_read_times * seek_time
	 + index_read_entry_counter * 24 / bandwidth);
	 double index_write_throughput = 1.0 * jcr.data_size / 1024 / 1024
	 / (index_write_times * seek_time
	 + index_write_entry_counter * 24 / bandwidth);*/

	/*	double estimated_throughput = write_data_throughput;
	 if (estimated_throughput > index_read_throughput)
	 estimated_throughput = index_read_throughput;*/
	/*if (estimated_throughput > index_write_throughput)
	 estimated_throughput = index_write_throughput;*/

	char logfile[] = "backup.log";
	FILE *fp = fopen(logfile, "a");
	/*
	 * job id,
	 * the size of backup
	 * accumulative consumed capacity,
	 * deduplication rate,
	 * rewritten rate,
	 * total container number,
	 * sparse container number,
	 * inherited container number,
	 * 4 * index overhead (4 * int)
	 * throughput,
	 */
	fprintf(fp, "%" PRId32 " %" PRId64 " %" PRId64 " %.4f %.4f %" PRId32 " %" PRId32 " %" PRId32 " %" PRId32" %" PRId32 " %" PRId32" %" PRId32" %.2f\n",
			jcr.id,
			jcr.data_size,
			destor.stored_data_size,
			jcr.data_size != 0 ?
					(jcr.data_size - jcr.rewritten_chunk_size - jcr.unique_data_size)/(double) (jcr.data_size)
					: 0,
			jcr.data_size != 0 ? (double) (jcr.rewritten_chunk_size) / (double) (jcr.data_size) : 0,
			jcr.total_container_num,
			jcr.sparse_container_num,
			jcr.inherited_sparse_num,
			index_overhead.lookup_requests,
			index_overhead.lookup_requests_for_unique,
			index_overhead.update_requests,
			index_overhead.read_prefetching_units,
			(double) jcr.data_size * 1000000 / (1024 * 1024 * jcr.total_time));

	fclose(fp);

}
Beispiel #8
0
void Shutdown(int flags)
{
	if ((flags & SHUTDOWN_FROM_CONFIG))
		goto from_config;

	EndGame();

	SAFE_DELETE(g_XmppClient);

	ShutdownPs();

	TIMER_BEGIN(L"shutdown TexMan");
	delete &g_TexMan;
	TIMER_END(L"shutdown TexMan");

	// destroy renderer
	TIMER_BEGIN(L"shutdown Renderer");
	delete &g_Renderer;
	g_VBMan.Shutdown();
	TIMER_END(L"shutdown Renderer");

	g_Profiler2.ShutdownGPU();

	#if OS_WIN
		TIMER_BEGIN(L"shutdown wmi");
		wmi_Shutdown();
		TIMER_END(L"shutdown wmi");
	#endif

	// Free cursors before shutting down SDL, as they may depend on SDL.
	cursor_shutdown();

	TIMER_BEGIN(L"shutdown SDL");
	ShutdownSDL();
	TIMER_END(L"shutdown SDL");

	g_VideoMode.Shutdown();

	TIMER_BEGIN(L"shutdown UserReporter");
	g_UserReporter.Deinitialize();
	TIMER_END(L"shutdown UserReporter");


	// JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
	//TIMER_BEGIN(L"shutdown DebuggingServer (if active)");
	//delete g_DebuggingServer;
	//TIMER_END(L"shutdown DebuggingServer (if active)");

	delete &g_L10n;

from_config:
	TIMER_BEGIN(L"shutdown ConfigDB");
	delete &g_ConfigDB;
	TIMER_END(L"shutdown ConfigDB");

	SAFE_DELETE(g_Console);

	// This is needed to ensure that no callbacks from the JSAPI try to use
	// the profiler when it's already destructed
	g_ScriptRuntime.reset();

	// resource
	// first shut down all resource owners, and then the handle manager.
	TIMER_BEGIN(L"resource modules");

		ISoundManager::SetEnabled(false);

		g_VFS.reset();

		// this forcibly frees all open handles (thus preventing real leaks),
		// and makes further access to h_mgr impossible.
		h_mgr_shutdown();

		file_stats_dump();

	TIMER_END(L"resource modules");

	TIMER_BEGIN(L"shutdown misc");
		timer_DisplayClientTotals();

		CNetHost::Deinitialize();

		// should be last, since the above use them
		SAFE_DELETE(g_Logger);
		delete &g_Profiler;
		delete &g_ProfileViewer;

		SAFE_DELETE(g_ScriptStatsTable);
	TIMER_END(L"shutdown misc");
}
Beispiel #9
0
void Shutdown(int UNUSED(flags))
{
	EndGame();

	ShutdownPs(); // Must delete g_GUI before g_ScriptingHost

	in_reset_handlers();

	TIMER_BEGIN(L"shutdown TexMan");
	delete &g_TexMan;
	TIMER_END(L"shutdown TexMan");

	// destroy renderer
	TIMER_BEGIN(L"shutdown Renderer");
	delete &g_Renderer;
	g_VBMan.Shutdown();
	TIMER_END(L"shutdown Renderer");

	tex_codec_unregister_all();

	g_Profiler2.ShutdownGPU();

	// Free cursors before shutting down SDL, as they may depend on SDL.
	cursor_shutdown();

	TIMER_BEGIN(L"shutdown SDL");
	ShutdownSDL();
	TIMER_END(L"shutdown SDL");

	g_VideoMode.Shutdown();

	TIMER_BEGIN(L"shutdown UserReporter");
	g_UserReporter.Deinitialize();
	TIMER_END(L"shutdown UserReporter");

	TIMER_BEGIN(L"shutdown ScriptingHost");
	delete &g_ScriptingHost;
	TIMER_END(L"shutdown ScriptingHost");

	TIMER_BEGIN(L"shutdown ConfigDB");
	delete &g_ConfigDB;
	TIMER_END(L"shutdown ConfigDB");

	// resource
	// first shut down all resource owners, and then the handle manager.
	TIMER_BEGIN(L"resource modules");
#if CONFIG2_AUDIO
		if (g_SoundManager)
			delete g_SoundManager;
#endif

		g_VFS.reset();

		// this forcibly frees all open handles (thus preventing real leaks),
		// and makes further access to h_mgr impossible.
		h_mgr_shutdown();

		file_stats_dump();

	TIMER_END(L"resource modules");

	TIMER_BEGIN(L"shutdown misc");
		timer_DisplayClientTotals();

		CNetHost::Deinitialize();

		SAFE_DELETE(g_ScriptStatsTable);

		// should be last, since the above use them
		SAFE_DELETE(g_Logger);
		delete &g_Profiler;
		delete &g_ProfileViewer;
	TIMER_END(L"shutdown misc");

#if OS_WIN
	TIMER_BEGIN(L"shutdown wmi");
	wmi_Shutdown();
	TIMER_END(L"shutdown wmi");
#endif
}
Beispiel #10
0
Container *container_cache_insert_container(ContainerCache *cc, ContainerId cid) {
	/* read container */
	Container *container = 0;
	TIMER_DECLARE(b, e);
	TIMER_BEGIN(b);

	if (cc->enable_data) {
		if (simulation_level >= SIMULATION_RECOVERY) {
			container = read_container_meta_only(cid);
		} else {
			container = read_container(cid);
		}
	} else {
		container = read_container_meta_only(cid);
	}

	TIMER_END(read_container_time, b, e);

	/* If this container is newly appended,
	 * maybe we can read nothing. */
	if (container == NULL) {
		return NULL;
	}

	/* insert */
	Container *evictor = lru_cache_insert(cc->lru_cache, container);

	/* evict */
	if (evictor) {
		int32_t chunknum = container_get_chunk_num(evictor);
		Fingerprint *fingers = container_get_all_fingers(evictor);
		int i = 0;
		/* evict all fingers of evictor from map */
		for (; i < chunknum; ++i) {
			GSequence* container_list = g_hash_table_lookup(cc->map,
					&fingers[i]);
			/* remove the specified container from list */
			GSequenceIter *iter = g_sequence_lookup(container_list, evictor,
					container_cmp_des, NULL);
			if (iter)
				g_sequence_remove(iter);
			else
				dprint("Error! The sequence does not contain the container.");
			if (g_sequence_get_length(container_list) == 0) {
				g_hash_table_remove(cc->map, &fingers[i]);
			}
		}
		free(fingers);
		if (fragment_stream)
			fprintf(fragment_stream, "%.4f\n",
					1.0 * evictor->used_size / CONTAINER_SIZE);
		container_free_full(evictor);
	}

	/* insert */
	int32_t num = container_get_chunk_num(container);
	Fingerprint *nfingers = container_get_all_fingers(container);
	int i = 0;
	for (; i < num; ++i) {
		GSequence* container_list = g_hash_table_lookup(cc->map, &nfingers[i]);
		if (container_list == 0) {
			container_list = g_sequence_new(NULL);
			Fingerprint *finger = (Fingerprint *) malloc(sizeof(Fingerprint));
			memcpy(finger, &nfingers[i], sizeof(Fingerprint));
			g_hash_table_insert(cc->map, finger, container_list);
		}
		g_sequence_insert_sorted(container_list, container, container_cmp_des,
				NULL);
	}
	free(nfingers);
	return container;
}
Beispiel #11
0
void do_restore(int revision, char *path) {

	init_recipe_store();
	init_container_store();

	init_restore_jcr(revision, path);

	destor_log(DESTOR_NOTICE, "job id: %d", jcr.id);
	destor_log(DESTOR_NOTICE, "backup path: %s", jcr.bv->path);
	destor_log(DESTOR_NOTICE, "restore to: %s", jcr.path);

	restore_chunk_queue = sync_queue_new(100);
	restore_recipe_queue = sync_queue_new(100);

	TIMER_DECLARE(1);
	TIMER_BEGIN(1);

	puts("==== restore begin ====");

	pthread_t recipe_t, read_t;
	pthread_create(&recipe_t, NULL, read_recipe_thread, NULL);

	if (destor.restore_cache[0] == RESTORE_CACHE_LRU) {
		destor_log(DESTOR_NOTICE, "restore cache is LRU");
		pthread_create(&read_t, NULL, lru_restore_thread, NULL);
	} else if (destor.restore_cache[0] == RESTORE_CACHE_OPT) {
		destor_log(DESTOR_NOTICE, "restore cache is OPT");
		pthread_create(&read_t, NULL, optimal_restore_thread, NULL);
	} else if (destor.restore_cache[0] == RESTORE_CACHE_ASM) {
		destor_log(DESTOR_NOTICE, "restore cache is ASM");
		pthread_create(&read_t, NULL, assembly_restore_thread, NULL);
	} else {
		fprintf(stderr, "Invalid restore cache.\n");
		exit(1);
	}

	write_restore_data();

	assert(sync_queue_size(restore_chunk_queue) == 0);
	assert(sync_queue_size(restore_recipe_queue) == 0);

	free_backup_version(jcr.bv);

	TIMER_END(1, jcr.total_time);
	puts("==== restore end ====");

	printf("job id: %d\n", jcr.id);
	printf("restore path: %s\n", jcr.path);
	printf("number of files: %d\n", jcr.file_num);
	printf("number of chunks: %d\n", jcr.chunk_num);
	printf("total size(B): %ld\n", jcr.data_size);
	printf("total time(s): %.3f\n", jcr.total_time / 1000000);
	printf("throughput(MB/s): %.2f\n",
			jcr.data_size * 1000000 / (1024.0 * 1024 * jcr.total_time));
	printf("speed factor: %.2f\n",
			jcr.data_size / (1024.0 * 1024 * jcr.read_container_num));

	printf("read_recipe_time : %.3fs, %.2fMB/s\n",
			jcr.read_recipe_time / 1000000,
			jcr.data_size * 1000000 / jcr.read_recipe_time / 1024 / 1024);
	printf("read_chunk_time : %.3fs, %.2fMB/s\n", jcr.read_chunk_time / 1000000,
			jcr.data_size * 1000000 / jcr.read_chunk_time / 1024 / 1024);
	printf("write_chunk_time : %.3fs, %.2fMB/s\n",
			jcr.write_chunk_time / 1000000,
			jcr.data_size * 1000000 / jcr.write_chunk_time / 1024 / 1024);

	char logfile[] = "restore.log";
	FILE *fp = fopen(logfile, "a");

	/*
	 * job id,
	 * chunk num,
	 * data size,
	 * actually read container number,
	 * speed factor,
	 * throughput
	 */
	fprintf(fp, "%d %lld %d %.4f %.4f\n", jcr.id, jcr.data_size,
			jcr.read_container_num,
			jcr.data_size / (1024.0 * 1024 * jcr.read_container_num),
			jcr.data_size * 1000000 / (1024 * 1024 * jcr.total_time));

	fclose(fp);

	close_container_store();
	close_recipe_store();
}
Beispiel #12
0
void write_restore_data() {

	char *p, *q;
	q = jcr.path + 1;/* ignore the first char*/
	/*
	 * recursively make directory
	 */
	while ((p = strchr(q, '/'))) {
		if (*p == *(p - 1)) {
			q++;
			continue;
		}
		*p = 0;
		if (access(jcr.path, 0) != 0) {
			mkdir(jcr.path, S_IRWXU | S_IRWXG | S_IRWXO);
		}
		*p = '/';
		q = p + 1;
	}

	struct chunk *c = NULL;
	FILE *fp = NULL;

	while ((c = sync_queue_pop(restore_chunk_queue))) {

		TIMER_DECLARE(1);
		TIMER_BEGIN(1);

		if (CHECK_CHUNK(c, CHUNK_FILE_START)) {
			NOTICE("Restoring: %s", c->data);

			sds filepath = sdsdup(jcr.path);
			filepath = sdscat(filepath, c->data);

			int len = sdslen(jcr.path);
			char *q = filepath + len;
			char *p;
			while ((p = strchr(q, '/'))) {
				if (*p == *(p - 1)) {
					q++;
					continue;
				}
				*p = 0;
				if (access(filepath, 0) != 0) {
					mkdir(filepath, S_IRWXU | S_IRWXG | S_IRWXO);
				}
				*p = '/';
				q = p + 1;
			}

			if (destor.simulation_level == SIMULATION_NO) {
				assert(fp == NULL);
				fp = fopen(filepath, "w");
			}

			sdsfree(filepath);

		} else if (CHECK_CHUNK(c, CHUNK_FILE_END)) {
			if (fp)
				fclose(fp);
			fp = NULL;
		} else {
			assert(destor.simulation_level == SIMULATION_NO);
			VERBOSE("Restoring %d bytes", c->size);
			fwrite(c->data, c->size, 1, fp);
		}

		free_chunk(c);

		TIMER_END(1, jcr.write_chunk_time);
	}

}
Beispiel #13
0
int main( int argc, char* argv[] ) {
	gnd::opsm::cmap_t				cmap;					// counting map
	gnd::opsm::map_t					map;					// scan matching map
	gnd::vector::fixed_column<3>	pos;					// matching result
	FILE							*fp;					// matched scan data (input)

	gnd::conf::parameter_array<char, 256> cmap_dir = {
			"cmap-dir", 							// item name
			"./", 									// default value
			"cmap directory path" 					// comment
	};
	gnd::conf::parameter_array<double, 3> pos_ini = {
			"init-pos", 							// item name
			{0, 0, 0}, 								// default value
			"initial position for scan matching (x[m], y[m], theta[deg])" 	// comment
	};
	gnd::conf::parameter_array<char, 256> scan_file = {
			"scan-data",							// item name
			"scan.txt",						// default value
			"scan data file path"					// comment
	};

	{ // ---> debug mode
		gnd::opsm::debug_set_log_level(2);
		gnd::gridmap::debug_set_log_level(2);
	} // <--- debug mode

	{ // ---> initialize
		int ret;
		gnd::conf::file_stream fs;

		// set parameter item and default parameter
		if( argc < 2 ) {
			static const char fname[] = "_scan-matching.conf";
			::fprintf(stderr, " error: missing file operand\n");
			::fprintf(stderr, "        please input configuration file path\n");
			::fprintf(stderr, "        e.g.: %s scan-matching.conf\n", argv[0]);
			::fprintf(stderr, "        ... \n");
			// write configuration file
			gnd::conf::set_parameter(&fs, &cmap_dir);
			gnd::conf::set_parameter(&fs, &pos_ini);
			gnd::conf::set_parameter(&fs, &scan_file);
			fs.write(fname);
			::fprintf(stderr, "         => generate configuration file template \"%s\"\n", fname);

			return -1;
		}

		// configuration file read
		ret = fs.read(argv[1]);
		if( ret < 0 ) {
			::fprintf(stderr, " error: fail to read configuration file\n");
			return -1;
		}

		// get parameter value
		gnd::conf::get_parameter(&fs, &cmap_dir);
		gnd::conf::get_parameter(&fs, &pos_ini);
		gnd::conf::get_parameter(&fs, &scan_file);

		if( !cmap_dir.value[0] ) {
			::fprintf(stdout, " error: missing counting map\n");
			::fprintf(stdout, " please set counting map directory\n");
			return -1;
		}

		// read counting map
		ret = gnd::opsm::read_counting_map( &cmap, cmap_dir.value );
		if( ret < 0 ) {
			::fprintf(stderr, " error: fail to read counting map form directory \"%s\"\n", cmap_dir.value);
			return 0;
		}

		// build scan matching map
		ret = gnd::opsm::build_map( &map, &cmap );

		if( !scan_file.value[0] ) {
			::fprintf(stdout, " error: missing scan data\n");
			::fprintf(stdout, "        please set scan data file\n");
			return -1;
		}

		// open scan data file
		fp = ::fopen( scan_file.value, "r" );
		if( !fp ) {
			::fprintf(stdout, " error: fail to open \"%s\"\n", scan_file.value);
			return -1;
		}

	} // <--- initialize



	{ // ---> operation
		int ret;
		gnd::opsm::mcl						mcl;		// quasi monte calro method class
		gnd::opsm::mcl::initial_parameter	mcl_ini;

		gnd::vector::fixed_column<3> 		delta;
		double 								likelihood;
		int 								cnt = 0;

		// timer init (for linux)
		TIMER_INIT();

		// set map
		mcl.set_map(&map);

		// set random seed
		gnd::random_set_seed();

		// initial position
		mcl_ini.pos[0] = pos_ini.value[0];
		mcl_ini.pos[1] = pos_ini.value[1];
		mcl_ini.pos[2] = pos_ini.value[2] * 3.141592 / 180;

		// number of particle
		mcl_ini.n = 300;

		// initial particles distribution
		// co-variance matrix
		gnd::matrix::set_zero( &mcl_ini.var_ini );
		mcl_ini.var_ini[0][0] = 0.1 * 0.1;									// x's standard deviation is 0.1
		mcl_ini.var_ini[1][1] = 0.1 * 0.1;									// y's standard deviation is 0.1
		mcl_ini.var_ini[2][2] = (10 * 3.141592 / 180) * (10 * 3.141592 / 180);	// orientation's standard deviation is 5 [deg]

		// set initial parameter
		mcl.begin( &mcl_ini );


		{// ---> set scan data (robot coordinate) and file out scan data on initial position
			FILE					*fp_ini;				// scan data on initial position (file out)
			double cosv = cos(mcl_ini.pos[2]);
			double sinv = sin(mcl_ini.pos[2]);

			// open output file (scan on initial position)
			fp_ini = ::fopen("scan-on-init-pos.txt", "w");
			if( !fp_ini ) {
				::fprintf(stdout, " error: fail to open \"%s\"\n", "scan-on-init-pos.txt");
				return -1;
			}

			while( !::feof(fp)  ) {
				double x, y;
				// read data file
				ret = ::fscanf(fp, "%lf %lf\n", &x, &y);
				// when read all data, break
				if( ret < 0 ) break;

				// set scan data
				mcl.set_scan_point( x, y );

				// file out scan data on initial position
				::fprintf(fp_ini, "%lf %lf\n",
						x * cosv - y * sinv + mcl_ini.pos[0],
						x * sinv + y * cosv + mcl_ini.pos[1]);
			}

			::fclose(fp_ini);
		} // ---> set scan data (robot coordinate) and file out scan data on initial position


		// set convergence test parameter
		// difference from previous position 0.001m in distance and 0.1deg in orientation
		mcl.set_converge_threshold( 0.001, 0.01 * 3.141592 / 180 );

		// show initial position
		::fprintf(stdout, "       init pos = %lf, %lf, %lf\n", mcl_ini.pos[0],  mcl_ini.pos[1],  mcl_ini.pos[2] * 180 / 3.141592);
		::fprintf(stdout, " scan point num = %d\n",  mcl.nscan_point());

		::fprintf(stdout, "\n");
		::fprintf(stdout, " => Scan Matching Begin\n");
		// iterative optimization
		double t = 0, l = 0;
		do {
			// optimize
			TIMER_BEGIN();
			mcl.iterate( &delta, &pos, &likelihood);
			TIMER_REC(&t, &l);

			cnt++;
			// show result
			::fprintf(stdout, "-------- optimization loop %d --------\n", cnt);
			::fprintf(stdout, "       delta = %lf, %lf, %lf\n", delta[0], delta[1], delta[2] * 180 / 3.141592);
			::fprintf(stdout, "         pos = %lf, %lf, %lf\n", pos[0], pos[1], pos[2] * 180 / 3.141592);
			::fprintf(stdout, "  likelihood = %lf\n", likelihood);
			TIMER_SHOW(&t, &l);
			::fprintf(stdout, "\n");
			::fprintf(stdout, "\n");

			// convergence test
		} while( !mcl.converge_test() || cnt < 5);

		::fprintf(stdout, " ... Finish\n");

	} // <--- operation


	{ // ---> finalize

		{ // ---> output matched scan data (global coordinate)
			int ret;
			double cosv = cos(pos[2]);
			double sinv = sin(pos[2]);
			FILE					*fp_m;					// scan data on matching position (file out)

			::fprintf(stdout, " => file-out matched scan points on global coordinate\n");


			// open output file (scan on matching position)
			fp_m = ::fopen("scan-on-match-pos.txt", "w");
			if( !fp_m ) {
				::fprintf(stdout, " error: fail to open \"%s\"\n", "scan-on-match-pos.txt");
				return -1;
			}

			// ---> fileout
			::fseek(fp, 0, SEEK_SET);
			while( !::feof(fp)  ) {
				double x, y;
				// read data file
				ret = ::fscanf(fp, "%lf %lf\n", &x, &y);
				// when read all data, break
				if( ret < 0 ) break;

				::fprintf(fp_m, "%lf %lf\n",
						x * cosv - y * sinv + pos[0],
						x * sinv + y * cosv + pos[1]
				);

			} // ---> fileout

			::fprintf(stdout, " ... output \"matched-scan-data.txt\"\n");

			// file close
			::fclose(fp_m);
		} // <--- output matched scan data (global coordinate)

		// file close
		::fclose(fp);

		gnd::opsm::destroy_counting_map(&cmap);
		gnd::opsm::destroy_map(&map);
	} // <--- finalize


	return 0;
}
Beispiel #14
0
/*
 * When a container buffer is full, we push it into container_queue.
 */
static void* filter_thread(void *arg) {
    int enable_rewrite = 1;
    struct fileRecipeMeta* r = NULL;

    while (1) {
        struct chunk* c = sync_queue_pop(rewrite_queue);

        if (c == NULL)
            /* backup job finish */
            break;

        /* reconstruct a segment */
        struct segment* s = new_segment();

        /* segment head */
        assert(CHECK_CHUNK(c, CHUNK_SEGMENT_START));
        free_chunk(c);

        c = sync_queue_pop(rewrite_queue);
        while (!(CHECK_CHUNK(c, CHUNK_SEGMENT_END))) {
            g_sequence_append(s->chunks, c);
            if (!CHECK_CHUNK(c, CHUNK_FILE_START)
                    && !CHECK_CHUNK(c, CHUNK_FILE_END))
                s->chunk_num++;

            c = sync_queue_pop(rewrite_queue);
        }
        free_chunk(c);

        /* For self-references in a segment.
         * If we find an early copy of the chunk in this segment has been rewritten,
         * the rewrite request for it will be denied to avoid repeat rewriting. */
        GHashTable *recently_rewritten_chunks = g_hash_table_new_full(g_int64_hash,
        		g_fingerprint_equal, NULL, free_chunk);
        GHashTable *recently_unique_chunks = g_hash_table_new_full(g_int64_hash,
        			g_fingerprint_equal, NULL, free_chunk);

        pthread_mutex_lock(&index_lock.mutex);

        TIMER_DECLARE(1);
        TIMER_BEGIN(1);
        /* This function will check the fragmented chunks
         * that would be rewritten later.
         * If we find an early copy of the chunk in earlier segments,
         * has been rewritten,
         * the rewrite request for it will be denied. */
        index_check_buffer(s);

    	GSequenceIter *iter = g_sequence_get_begin_iter(s->chunks);
    	GSequenceIter *end = g_sequence_get_end_iter(s->chunks);
        for (; iter != end; iter = g_sequence_iter_next(iter)) {
            c = g_sequence_get(iter);

    		if (CHECK_CHUNK(c, CHUNK_FILE_START) || CHECK_CHUNK(c, CHUNK_FILE_END))
    			continue;

            VERBOSE("Filter phase: %dth chunk in %s container %lld", chunk_num,
                    CHECK_CHUNK(c, CHUNK_OUT_OF_ORDER) ? "out-of-order" : "", c->id);

            /* Cache-Aware Filter */
            if (destor.rewrite_enable_cache_aware && restore_aware_contains(c->id)) {
                assert(c->id != TEMPORARY_ID);
                VERBOSE("Filter phase: %dth chunk is cached", chunk_num);
                SET_CHUNK(c, CHUNK_IN_CACHE);
            }

            /* A cfl-switch for rewriting out-of-order chunks. */
            if (destor.rewrite_enable_cfl_switch) {
                double cfl = restore_aware_get_cfl();
                if (enable_rewrite && cfl > destor.rewrite_cfl_require) {
                    VERBOSE("Filter phase: Turn OFF the (out-of-order) rewrite switch of %.3f",
                            cfl);
                    enable_rewrite = 0;
                } else if (!enable_rewrite && cfl < destor.rewrite_cfl_require) {
                    VERBOSE("Filter phase: Turn ON the (out-of-order) rewrite switch of %.3f",
                            cfl);
                    enable_rewrite = 1;
                }
            }

            if(CHECK_CHUNK(c, CHUNK_DUPLICATE) && c->id == TEMPORARY_ID){
            	struct chunk* ruc = g_hash_table_lookup(recently_unique_chunks, &c->fp);
            	assert(ruc);
            	c->id = ruc->id;
            }
            struct chunk* rwc = g_hash_table_lookup(recently_rewritten_chunks, &c->fp);
            if(rwc){
            	c->id = rwc->id;
            	SET_CHUNK(c, CHUNK_REWRITE_DENIED);
            }

            /* A fragmented chunk will be denied if it has been rewritten recently */
            if (!CHECK_CHUNK(c, CHUNK_DUPLICATE) || (!CHECK_CHUNK(c, CHUNK_REWRITE_DENIED)
            		&& (CHECK_CHUNK(c, CHUNK_SPARSE)
                    || (enable_rewrite && CHECK_CHUNK(c, CHUNK_OUT_OF_ORDER)
                        && !CHECK_CHUNK(c, CHUNK_IN_CACHE))))) {
                /*
                 * If the chunk is unique, or be fragmented and not denied,
                 * we write it to a container.
                 * Fragmented indicates: sparse, or out of order and not in cache,
                 */
                if (storage_buffer.container_buffer == NULL){
                	storage_buffer.container_buffer = create_container();
                	if(destor.index_category[1] == INDEX_CATEGORY_PHYSICAL_LOCALITY)
                		storage_buffer.chunks = g_sequence_new(free_chunk);
                }

                if (container_overflow(storage_buffer.container_buffer, c->size)) {

                    if(destor.index_category[1] == INDEX_CATEGORY_PHYSICAL_LOCALITY){
                        /*
                         * TO-DO
                         * Update_index for physical locality
                         */
                        GHashTable *features = sampling(storage_buffer.chunks,
                        		g_sequence_get_length(storage_buffer.chunks));
                        index_update(features, get_container_id(storage_buffer.container_buffer));
                        g_hash_table_destroy(features);
                        g_sequence_free(storage_buffer.chunks);
                        storage_buffer.chunks = g_sequence_new(free_chunk);
                    }
                    TIMER_END(1, jcr.filter_time);
                    write_container_async(storage_buffer.container_buffer);
                    TIMER_BEGIN(1);
                    storage_buffer.container_buffer = create_container();
                }

                if(add_chunk_to_container(storage_buffer.container_buffer, c)){

                	struct chunk* wc = new_chunk(0);
                	memcpy(&wc->fp, &c->fp, sizeof(fingerprint));
                	wc->id = c->id;
                	if (!CHECK_CHUNK(c, CHUNK_DUPLICATE)) {
                		jcr.unique_chunk_num++;
                		jcr.unique_data_size += c->size;
                		g_hash_table_insert(recently_unique_chunks, &wc->fp, wc);
                    	VERBOSE("Filter phase: %dth chunk is recently unique, size %d", chunk_num,
                    			g_hash_table_size(recently_unique_chunks));
                	} else {
                		jcr.rewritten_chunk_num++;
                		jcr.rewritten_chunk_size += c->size;
                		g_hash_table_insert(recently_rewritten_chunks, &wc->fp, wc);
                	}

                	if(destor.index_category[1] == INDEX_CATEGORY_PHYSICAL_LOCALITY){
                		struct chunk* ck = new_chunk(0);
                		memcpy(&ck->fp, &c->fp, sizeof(fingerprint));
                		g_sequence_append(storage_buffer.chunks, ck);
                	}

                	VERBOSE("Filter phase: Write %dth chunk to container %lld",
                			chunk_num, c->id);
                }else{
                	VERBOSE("Filter phase: container %lld already has this chunk", c->id);
            		assert(destor.index_category[0] != INDEX_CATEGORY_EXACT
            				|| destor.rewrite_algorithm[0]!=REWRITE_NO);
                }

            }else{
                if(CHECK_CHUNK(c, CHUNK_REWRITE_DENIED)){
                    VERBOSE("Filter phase: %lldth fragmented chunk is denied", chunk_num);
                }else if (CHECK_CHUNK(c, CHUNK_OUT_OF_ORDER)) {
                    VERBOSE("Filter phase: %lldth chunk in out-of-order container %lld is already cached",
                            chunk_num, c->id);
                }
            }

            assert(c->id != TEMPORARY_ID);

            /* Collect historical information. */
            har_monitor_update(c->id, c->size);

            /* Restore-aware */
            restore_aware_update(c->id, c->size);

            chunk_num++;
        }

        int full = index_update_buffer(s);

        /* Write a SEGMENT_BEGIN */
        segmentid sid = append_segment_flag(jcr.bv, CHUNK_SEGMENT_START, s->chunk_num);

        /* Write recipe */
    	iter = g_sequence_get_begin_iter(s->chunks);
    	end = g_sequence_get_end_iter(s->chunks);
        for (; iter != end; iter = g_sequence_iter_next(iter)) {
            c = g_sequence_get(iter);

        	if(r == NULL){
        		assert(CHECK_CHUNK(c,CHUNK_FILE_START));
        		r = new_file_recipe_meta(c->data);
        	}else if(!CHECK_CHUNK(c,CHUNK_FILE_END)){
        		struct chunkPointer cp;
        		cp.id = c->id;
        		assert(cp.id>=0);
        		memcpy(&cp.fp, &c->fp, sizeof(fingerprint));
        		cp.size = c->size;
        		append_n_chunk_pointers(jcr.bv, &cp ,1);
        		r->chunknum++;
        		r->filesize += c->size;

    	    	jcr.chunk_num++;
	    	    jcr.data_size += c->size;

        	}else{
        		assert(CHECK_CHUNK(c,CHUNK_FILE_END));
        		append_file_recipe_meta(jcr.bv, r);
        		free_file_recipe_meta(r);
        		r = NULL;

	            jcr.file_num++;
        	}
        }

       	/* Write a SEGMENT_END */
       	append_segment_flag(jcr.bv, CHUNK_SEGMENT_END, 0);

        if(destor.index_category[1] == INDEX_CATEGORY_LOGICAL_LOCALITY){
             /*
              * TO-DO
              * Update_index for logical locality
              */
            s->features = sampling(s->chunks, s->chunk_num);
         	if(destor.index_category[0] == INDEX_CATEGORY_EXACT){
         		/*
         		 * For exact deduplication,
         		 * unique fingerprints are inserted.
         		 */
         		VERBOSE("Filter phase: add %d unique fingerprints to %d features",
         				g_hash_table_size(recently_unique_chunks),
         				g_hash_table_size(s->features));
         		GHashTableIter iter;
         		gpointer key, value;
         		g_hash_table_iter_init(&iter, recently_unique_chunks);
         		while(g_hash_table_iter_next(&iter, &key, &value)){
         			struct chunk* uc = value;
         			fingerprint *ft = malloc(sizeof(fingerprint));
         			memcpy(ft, &uc->fp, sizeof(fingerprint));
         			g_hash_table_insert(s->features, ft, NULL);
         		}

         		/*
         		 * OPTION:
         		 * 	It is still an open problem whether we need to update
         		 * 	rewritten fingerprints.
         		 * 	It would increase index update overhead, while the benefit
         		 * 	remains unclear.
         		 * 	More experiments are required.
         		 */
         		VERBOSE("Filter phase: add %d rewritten fingerprints to %d features",
         				g_hash_table_size(recently_rewritten_chunks),
         				g_hash_table_size(s->features));
         		g_hash_table_iter_init(&iter, recently_rewritten_chunks);
         		while(g_hash_table_iter_next(&iter, &key, &value)){
         			struct chunk* uc = value;
         			fingerprint *ft = malloc(sizeof(fingerprint));
         			memcpy(ft, &uc->fp, sizeof(fingerprint));
         			g_hash_table_insert(s->features, ft, NULL);
         		}
         	}
         	index_update(s->features, sid);
         }

        free_segment(s);

        if(index_lock.wait_threshold > 0 && full == 0){
        	pthread_cond_broadcast(&index_lock.cond);
        }
        TIMER_END(1, jcr.filter_time);
        pthread_mutex_unlock(&index_lock.mutex);

        g_hash_table_destroy(recently_rewritten_chunks);
        g_hash_table_destroy(recently_unique_chunks);

    }

    if (storage_buffer.container_buffer
    		&& !container_empty(storage_buffer.container_buffer)){
        if(destor.index_category[1] == INDEX_CATEGORY_PHYSICAL_LOCALITY){
            /*
             * TO-DO
             * Update_index for physical locality
             */
        	GHashTable *features = sampling(storage_buffer.chunks,
        			g_sequence_get_length(storage_buffer.chunks));
        	index_update(features, get_container_id(storage_buffer.container_buffer));
        	g_hash_table_destroy(features);
        	g_sequence_free(storage_buffer.chunks);
        }
        write_container_async(storage_buffer.container_buffer);
    }

    /* All files done */
    jcr.status = JCR_STATUS_DONE;
    return NULL;
}