Ejemplo n.º 1
0
const char *do_uemis_import(const char *mountpath, short force_download)
{
	char *newmax = NULL;
	int start, end = -2, i, offset;
	uint32_t deviceidnr;
	char objectid[10];
	char *deviceid = NULL;
	const char *result = NULL;
	char *endptr;
	bool success, keep_number = false, once = true;

	if (dive_table.nr == 0)
		keep_number = true;
	uemis_info(translate("gettextFromC", "Init Communication"));
	if (!uemis_init(mountpath))
		return translate("gettextFromC", "Uemis init failed");
	if (!uemis_get_answer(mountpath, "getDeviceId", 0, 1, &result))
		goto bail;
	deviceid = strdup(param_buff[0]);
	deviceidnr = atoi(deviceid);
	/* the answer from the DeviceId call becomes the input parameter for getDeviceData */
	if (!uemis_get_answer(mountpath, "getDeviceData", 1, 0, &result))
		goto bail;
	/* param_buff[0] is still valid */
	if (!uemis_get_answer(mountpath, "initSession", 1, 6, &result))
		goto bail;
	uemis_info(translate("gettextFromC", "Start download"));
	if (!uemis_get_answer(mountpath, "processSync", 0, 2, &result))
		goto bail;
	/* before starting the long download, check if user pressed cancel */
	if (import_thread_cancelled)
		goto bail;
	param_buff[1] = "notempty";
	/* if we have an empty divelist or force it, then we start downloading from the
	 * first dive on the Uemis; otherwise check which was the last dive downloaded */
	if (!force_download && dive_table.nr > 0)
		newmax = uemis_get_divenr(deviceid);
	else
		newmax = strdup("0");
	start = atoi(newmax);
	for (;;) {
#if UEMIS_DEBUG & 4
		fprintf(debugfile, "d_u_i inner loop start %d end %d newmax %s\n", start, end, newmax);
#endif
		param_buff[2] = newmax;
		param_buff[3] = 0;
		success = uemis_get_answer(mountpath, "getDivelogs", 3, 0, &result);
		/* process the buffer we have assembled */
		if (mbuf)
			if (!process_raw_buffer(deviceidnr, mbuf, &newmax, keep_number, NULL)) {
				/* if no dives were downloaded, mark end appropriately */
				if (end == -2)
					end = start - 1;
				success = false;
			}
		if (once) {
			char *t = first_object_id_val(mbuf);
			if (t && atoi(t) > start)
				start = atoi(t);
			free(t);
			once = false;
		}
#if UEMIS_DEBUG & 4
		fprintf(debugfile, "d_u_i after download and parse start %d end %d newmax %s\n", start, end, newmax);
#endif
		/* if the user clicked cancel, exit gracefully */
		if (import_thread_cancelled)
			goto bail;
		/* if we got an error or got nothing back, stop trying */
		if (!success || !param_buff[3])
			break;
		/* finally, if the memory is getting too full, maybe we better stop, too */
		if (progress_bar_fraction > 0.85) {
			result = translate("gettextFromC", ERR_FS_ALMOST_FULL);
			break;
		}
		/* clean up mbuf */
		endptr = strstr(mbuf, "{{{");
		if (endptr)
			*(endptr + 2) = '\0';
		/* last object_id we parsed */
		sscanf(newmax, "%d", &end);
	}
	if (end == -2 && sscanf(newmax, "%d", &end) != 1)
		end = start;
#if UEMIS_DEBUG & 2
	fprintf(debugfile, "done: read from object_id %d to %d\n", start, end);
#endif
	free(newmax);
	offset = 0;
	for (i = start; i <= end; i++) {
		snprintf(objectid, sizeof(objectid), "%d", i + offset);
		param_buff[2] = objectid;
#if UEMIS_DEBUG & 2
		fprintf(debugfile, "getDive %d, object_id %s\n", i, objectid);
#endif
		/* there is no way I have found to directly get the dive information
		 * for dive #i as the object_id and logfilenr can be different in the
		 * getDive call; so we get the first one, compare the actual divenr
		 * with the one that we wanted, calculate the offset and try again.
		 * What an insane design... */
		success = uemis_get_answer(mountpath, "getDive", 3, 0, &result);
		if (mbuf) {
			int divenr;
			(void)process_raw_buffer(deviceidnr, mbuf, &newmax, false, &divenr);
#if UEMIS_DEBUG & 2
			fprintf(debugfile, "got dive %d, looking for dive %d\n", divenr, i);
#endif
			if (divenr != i) {
				if (divenr == -1) {
					offset--;
				} else {
					offset += i - divenr;
				}
#if UEMIS_DEBUG & 2
				fprintf(debugfile, " -> trying again with offset %d\n", offset);
#endif
				i = start - 1;
				if (i + offset < 0)
					break;
				continue;
			}
		}
		if (!success || import_thread_cancelled)
			break;
	}
	success = true;
	for (i = 0; i <= nr_divespots; i++) {
		char divespotnr[10];
		snprintf(divespotnr, sizeof(divespotnr), "%d", i);
		param_buff[2] = divespotnr;
#if UEMIS_DEBUG & 2
		fprintf(debugfile, "getDivespot %d\n", i);
#endif
		success = uemis_get_answer(mountpath, "getDivespot", 3, 0, &result);
		if (mbuf)
			parse_divespot(mbuf);
	}
bail:
	(void)uemis_get_answer(mountpath, "terminateSync", 0, 3, &result);
	if (!strcmp(param_buff[0], "error")) {
		if (!strcmp(param_buff[2], "Out of Memory"))
			result = translate("gettextFromC", ERR_FS_FULL);
		else
			result = param_buff[2];
	}
	free(deviceid);
	return result;
}
Ejemplo n.º 2
0
const char *do_uemis_import(device_data_t *data)
{
	const char *mountpath = data->devname;
	short force_download = data->force_download;
	char *newmax = NULL;
	int first, start, end = -2;
	uint32_t deviceidnr;
	char *deviceid = NULL;
	const char *result = NULL;
	char *endptr;
	bool success, keep_number = false, once = true;
	int match_dive_and_log = 0;
	int uemis_mem_status = UEMIS_MEM_OK;

#if UEMIS_DEBUG
	home = getenv("HOME");
	user = getenv("LOGNAME");
#endif
	if (dive_table.nr == 0)
		keep_number = true;

	uemis_info(translate("gettextFromC", "Initialise communication"));
	if (!uemis_init(mountpath)) {
		free(reqtxt_path);
		return translate("gettextFromC", "Uemis init failed");
	}

	if (!uemis_get_answer(mountpath, "getDeviceId", 0, 1, &result))
		goto bail;
	deviceid = strdup(param_buff[0]);
	deviceidnr = atoi(deviceid);

	/* param_buff[0] is still valid */
	if (!uemis_get_answer(mountpath, "initSession", 1, 6, &result))
		goto bail;

	uemis_info(translate("gettextFromC", "Start download"));
	if (!uemis_get_answer(mountpath, "processSync", 0, 2, &result))
		goto bail;

	/* before starting the long download, check if user pressed cancel */
	if (import_thread_cancelled)
		goto bail;

	param_buff[1] = "notempty";
	newmax = uemis_get_divenr(deviceid, force_download);
	if (verbose)
		fprintf(stderr, "Uemis downloader: start looking at dive nr %s", newmax);

	first = start = atoi(newmax);
	dive_to_read = first;
	for (;;) {
#if UEMIS_DEBUG & 2
		debug_round++;
#endif
#if UEMIS_DEBUG & 4
		fprintf(debugfile, "d_u_i inner loop start %d end %d newmax %s\n", start, end, newmax);
#endif
		/* start at the last filled download table index */
		match_dive_and_log = data->download_table->nr;
		sprintf(newmax, "%d", start);
		param_buff[2] = newmax;
		param_buff[3] = 0;
		success = uemis_get_answer(mountpath, "getDivelogs", 3, 0, &result);
		uemis_mem_status = get_memory(data->download_table, UEMIS_CHECK_DETAILS);
		if (success && mbuf && uemis_mem_status != UEMIS_MEM_FULL) {
#if UEMIS_DEBUG & 16
			do_dump_buffer_to_file(mbuf, "Divelogs");
#endif
			/* process the buffer we have assembled */

			if (!process_raw_buffer(data, deviceidnr, mbuf, &newmax, keep_number, NULL)) {
				/* if no dives were downloaded, mark end appropriately */
				if (end == -2)
					end = start - 1;
				success = false;
			}
			if (once) {
				char *t = first_object_id_val(mbuf);
				if (t && atoi(t) > start)
					start = atoi(t);
				free(t);
				once = false;
			}
			/* clean up mbuf */
			endptr = strstr(mbuf, "{{{");
			if (endptr)
				*(endptr + 2) = '\0';
			/* last object_id we parsed */
			sscanf(newmax, "%d", &end);
#if UEMIS_DEBUG & 4
			fprintf(debugfile, "d_u_i after download and parse start %d end %d newmax %s progress %4.2f\n", start, end, newmax, progress_bar_fraction);
#endif
			/* The way this works is that I am reading the current dive from what has been loaded during the getDiveLogs call to the UEMIS.
			 * As the object_id of the divelog entry and the object_id of the dive details are not necessarily the same, the match needs
			 * to happen based on the logfilenr.
			 * What the following part does is to optimize the mapping by using
			 * dive_to_read = the dive deatils entry that need to be read using the object_id
			 * logFileNoToFind = map the logfilenr of the dive details with the object_id = diveid from the get dive logs */
			for (int i = match_dive_and_log; i < data->download_table->nr; i++) {
				bool success = get_matching_dive(i, newmax, &uemis_mem_status, data, mountpath, deviceidnr);
				if (!success)
					break;
				if (import_thread_cancelled)
					break;
			}

			start = end;

			/* Do some memory checking here */
			uemis_mem_status = get_memory(data->download_table, UEMIS_CHECK_LOG);
			if (uemis_mem_status != UEMIS_MEM_OK) {
#if UEMIS_DEBUG & 4
				fprintf(debugfile, "d_u_i out of memory, bailing\n");
#endif
				break;
			}
			/* if the user clicked cancel, exit gracefully */
			if (import_thread_cancelled) {
#if UEMIS_DEBUG & 4
				fprintf(debugfile, "d_u_i thread cancelled, bailing\n");
#endif
				break;
			}
			/* if we got an error or got nothing back, stop trying */
			if (!success || !param_buff[3]) {
#if UEMIS_DEBUG & 4
				fprintf(debugfile, "d_u_i after download nothing found, giving up\n");
#endif
				break;
			}
#if UEMIS_DEBUG & 2
			if (debug_round != -1)
				if (debug_round-- == 0) {
					fprintf(debugfile, "d_u_i debug_round is now 0, bailing\n");
					goto bail;
				}
#endif
		} else {
			/* some of the loading from the UEMIS failed at the divelog level
			 * if the memory status = full, we cant even load the divespots and/or buddys.
			 * The loaded block of divelogs is useless and all new loaded divelogs need to
			 * be deleted from the download_table.
			 */
			if (uemis_mem_status == UEMIS_MEM_FULL)
				do_delete_dives(data->download_table, match_dive_and_log);
#if UEMIS_DEBUG & 4
			fprintf(debugfile, "d_u_i out of memory, bailing instead of processing\n");
#endif
			break;
		}
	}

	if (end == -2 && sscanf(newmax, "%d", &end) != 1)
		end = start;

#if UEMIS_DEBUG & 2
	fprintf(debugfile, "Done: read from object_id %d to %d\n", first, end);
#endif

	/* Regardless on where we are with the memory situation, it's time now
	 * to see if we have to clean some dead bodies from our download table */
	next_table_index = 0;
	while (next_table_index < data->download_table->nr) {
		if (!data->download_table->dives[next_table_index]->downloaded)
			uemis_delete_dive(data, data->download_table->dives[next_table_index]->dc.diveid);
		else
			next_table_index++;
	}

	if (uemis_mem_status != UEMIS_MEM_OK)
		result = translate("gettextFromC", ERR_FS_ALMOST_FULL);

bail:
	(void)uemis_get_answer(mountpath, "terminateSync", 0, 3, &result);
	if (!strcmp(param_buff[0], "error")) {
		if (!strcmp(param_buff[2], "Out of Memory"))
			result = translate("gettextFromC", ERR_FS_FULL);
		else
			result = param_buff[2];
	}
	free(deviceid);
	free(reqtxt_path);
	if (!data->download_table->nr)
		result = translate("gettextFromC", ERR_NO_FILES);
	return result;
}