コード例 #1
0
static int custom_update_thread(void* thread_data)
{
	SDL_Event event;
	UpdateThreaData_t* data;
	Uint32 result;

	result = 0;
	data = (UpdateThreaData_t*)thread_data;

	init_thread_log("custom_update");

	while (1)
	{
		CHECK_AND_LOCK_MUTEX(data->mutex);

		data->error = result;

		while (data->running == 1)
		{
			SDL_CondWait(data->condition, data->mutex);
		}

		if (data->running == 0)
		{
			CHECK_AND_UNLOCK_MUTEX(data->mutex);

			return 1;
		}

		data->error = 0;
		safe_snprintf(data->str, sizeof(data->str), "%s custom updates: %s",
			data->name, "started");

		CHECK_AND_UNLOCK_MUTEX(data->mutex);

		result = custom_update_threaded(data->dir, data->zip, data);

		CHECK_AND_LOCK_MUTEX(data->mutex);

		if (data->running == 2)
		{
			data->running = 1;
		}

		LOG_INFO("%s", data->str);

		CHECK_AND_UNLOCK_MUTEX(data->mutex);

		// signal we are done
		event.type = SDL_USEREVENT;
		event.user.code = EVENT_CUSTOM_UPDATE_COMPLETE;
		event.user.data1 = 0;
		SDL_PushEvent(&event);
	}

	return 0;
}
コード例 #2
0
static el_file_ptr file_open(const char* file_name, const char* extra_path)
{
	char str[1024];
	el_zip_file_entry_t key;
	el_file_ptr result;
	Sint32 i, count;

	if (!file_name || !*file_name)
		return NULL;

	if (extra_path)
	{
		if (do_file_exists(file_name, extra_path, sizeof(str), str) == 1)
		{
			return xz_gz_file_open(str);
		}
	}

	if (do_file_exists(file_name, get_path_updates(), sizeof(str), str) == 1)
	{
		return xz_gz_file_open(str);
	}

	init_key(file_name, &key, sizeof(str), str);

	CHECK_AND_LOCK_MUTEX(zip_mutex);

	count = num_zip_files - 1;

	CHECK_AND_UNLOCK_MUTEX(zip_mutex);

	for (i = count; i >= 0; i--)
	{
		CHECK_AND_LOCK_MUTEX(zip_files[i].mutex);

		if (locate_in_zip(&zip_files[i], &key) == 1)
		{
			result = zip_file_open(zip_files[i].file);

			CHECK_AND_UNLOCK_MUTEX(zip_files[i].mutex);

			return result;
		}

		CHECK_AND_UNLOCK_MUTEX(zip_files[i].mutex);
	}

	if (do_file_exists(file_name, datadir, sizeof(str), str) == 1)
	{
		return xz_gz_file_open(str);
	}

	LOG_ERROR("Can't open file '%s'.", file_name);

	return NULL;
}
コード例 #3
0
static Uint32 file_exists_path(const char* file_name, const char* extra_path)
{
	char str[1024];
	el_zip_file_entry_t key;
	Sint32 i, count;

	if (file_name == 0)
	{
		return 0;
	}

	if (extra_path != 0)
	{
		if (do_file_exists(file_name, extra_path, sizeof(str), str) == 1)
		{
			return 1;
		}
	}

	if (do_file_exists(file_name, get_path_updates(), sizeof(str), str) == 1)
	{
		return 1;
	}

	init_key(file_name, &key, sizeof(str), str);

	CHECK_AND_LOCK_MUTEX(zip_mutex);

	count = num_zip_files - 1;

	CHECK_AND_UNLOCK_MUTEX(zip_mutex);

	for (i = count; i >= 0; i--)
	{
		CHECK_AND_LOCK_MUTEX(zip_files[i].mutex);

		if (find_in_zip(&zip_files[i], &key) == 1)
		{
			CHECK_AND_UNLOCK_MUTEX(zip_files[i].mutex);

			return 1;
		}

		CHECK_AND_UNLOCK_MUTEX(zip_files[i].mutex);
	}

	if (do_file_exists(file_name, datadir, sizeof(str), str) == 1)
	{
		return 1;
	}

	return 0;
}
コード例 #4
0
void unload_zip_archive(const char* file_name)
{
	Uint32 i, count;

	if (file_name == 0)
	{
		LOG_ERROR("Invalid file name");

		return;
	}

	ENTER_DEBUG_MARK("unload zip");

	LOG_DEBUG("Unloading zip '%s'.", file_name);

	CHECK_AND_LOCK_MUTEX(zip_mutex);

	count = num_zip_files;

	CHECK_AND_UNLOCK_MUTEX(zip_mutex);

	LOG_DEBUG("Checking %d zip files", count);

	for (i = 0; i < count; i++)
	{
		CHECK_AND_LOCK_MUTEX(zip_files[i].mutex);

		LOG_DEBUG("Checking zip file '%s'", zip_files[i].file_name);

		if (zip_files[i].file_name != 0)
		{
			if (strcmp(zip_files[i].file_name, file_name) == 0)
			{
				clear_zip(&zip_files[i]);

				CHECK_AND_UNLOCK_MUTEX(zip_files[i].mutex);

				LEAVE_DEBUG_MARK("unload zip");

				return;
			}
		}

		CHECK_AND_UNLOCK_MUTEX(zip_files[i].mutex);
	}

	LEAVE_DEBUG_MARK("unload zip");
}
コード例 #5
0
ファイル: queue.c プロジェクト: sorlok/Eternal-Lands
void *queue_pop_blocking(queue_t *queue)
{
	node_t *node;
	void *item;

	if (queue == 0)
	{
		return 0;
	}
	CHECK_AND_LOCK_MUTEX(queue->mutex);

	while (queue->front == queue->rear)
	{
		SDL_CondWait(queue->condition, queue->mutex);
	}

	node = queue->front->next;
	item = node->data;
	/* Check if removing the last node from the queue */
	if (queue->front->next->next == 0)
	{
		queue->rear = queue->front;
	}
	else
	{
		queue->front->next = queue->front->next->next;
	}

	free(node);
	queue->nodes--;
	CHECK_AND_UNLOCK_MUTEX(queue->mutex);

	return item;
}
コード例 #6
0
ファイル: queue.c プロジェクト: sorlok/Eternal-Lands
int queue_push (queue_t *queue, void *item)
{
	node_t *newnode;

	if (queue == 0)
	{
		LOG_ERROR("Null pointer for queue");

		return 0;
	}

	newnode = malloc(sizeof(node_t));

	if (newnode == 0)
	{
		LOG_ERROR("Failed to allocate memory for queue node");

		return 0;
	}

	newnode->data = item;
	newnode->next = 0;
	/* Add to the end of the queue */
	CHECK_AND_LOCK_MUTEX(queue->mutex);
	queue->rear->next = newnode;
	queue->rear = newnode;
	queue->nodes++;
	CHECK_AND_UNLOCK_MUTEX(queue->mutex);

	return 1;
}
コード例 #7
0
ファイル: queue.c プロジェクト: sorlok/Eternal-Lands
void *queue_pop (queue_t *queue)
{
	node_t *oldnode;
	void *item;

	if (queue == NULL || queue_isempty(queue))
	{
		return NULL;
	}
	else
	{
		CHECK_AND_LOCK_MUTEX(queue->mutex);
		oldnode = queue->front->next;
		item = oldnode->data;
		/* Check if removing the last node from the queue */
		if (queue->front->next->next == NULL)
		{
			queue->rear = queue->front;
		}
		else
		{
			queue->front->next = queue->front->next->next;
		}
		free(oldnode);
		queue->nodes--;
		CHECK_AND_UNLOCK_MUTEX(queue->mutex);
		return item;
	}
}
コード例 #8
0
static Uint32 progress_function(const char* str, const Uint32 max,
	const Uint32 current, void* user_data)
{
	UpdateThreaData_t* data;

	data = (UpdateThreaData_t*)user_data;

	CHECK_AND_LOCK_MUTEX(data->mutex);

	if (max > 0)
	{
		safe_snprintf(data->str, sizeof(data->str),
			"%s custom updates: %s %.2f%%", data->name,
			str, (current * 100.0f) / max);
	}
	else
	{
		safe_snprintf(data->str, sizeof(data->str),
			"%s custom updates: %s", data->name, str);
	}

	LOG_INFO("%s", data->str);

	if (data->running == 0)
	{
		CHECK_AND_UNLOCK_MUTEX(data->mutex);

		return 0;
	}

	CHECK_AND_UNLOCK_MUTEX(data->mutex);

	return 1;
}
コード例 #9
0
ファイル: queue.c プロジェクト: sorlok/Eternal-Lands
void queue_destroy (queue_t *queue)
{
	void *tmp;

	if (queue != NULL)
	{
		//Tell our queue manager that we're done.
		stop_managing_queue(queue);

		CHECK_AND_LOCK_MUTEX(queue->mutex);
		while (!queue_isempty (queue))
		{
			if ((tmp = queue_pop(queue)) == NULL)
			{
				break;
			}
			else
			{
				free(tmp);
			}
		}
		/* Free the dummy node too */
		free(queue->front);
		CHECK_AND_UNLOCK_MUTEX(queue->mutex);
		SDL_DestroyMutex(queue->mutex);
#ifdef	NEW_TEXTURES
		SDL_DestroyCond(queue->condition);
#endif	/* NEW_TEXTURES */
		free (queue);
	}
}
コード例 #10
0
ファイル: queue.c プロジェクト: sorlok/Eternal-Lands
int queue_isempty(const queue_t *queue)
{
	int return_value;

	if (queue == NULL)
	{
		return_value = 1;
	}
	else
	{
		CHECK_AND_LOCK_MUTEX(queue->mutex);
		return_value = (queue->front == queue->rear);
		CHECK_AND_UNLOCK_MUTEX(queue->mutex);
	}
	return return_value;
}
コード例 #11
0
ファイル: queue.c プロジェクト: sorlok/Eternal-Lands
void *queue_delete_node(queue_t *queue, node_t *node)
{
	if (queue == NULL || node == NULL || queue_isempty(queue))
	{
		return NULL;
	}
	else
	{
		void *data = NULL;
		node_t *search_node;

		CHECK_AND_LOCK_MUTEX(queue->mutex);
		search_node = queue->front;
		/* Find the node in the queue */
		/* Check if it's the first node. */
		if (node == queue->front)
		{
			/* Shouldn't really happen */
			return NULL;
		}
		else
		{
			while(search_node != NULL)
			{
				/* Check if the next node is what we're looking for */
				if (search_node->next == node)
				{
					/* Point the  node before our node's  next pointer to the node after our node  */
					search_node->next = node->next;
					if (node == queue->rear)
					{
						queue->rear = search_node;
					}
					/* Make sure the data isn't lost when we free the node */
					data = node->data;
					free(node);
					queue->nodes--;
					break;
				}
				search_node = search_node->next;
			}
		}
		CHECK_AND_UNLOCK_MUTEX(queue->mutex);
		return data;
	}
}
コード例 #12
0
void start_custom_update()
{
	Uint32 i;

	for (i = 0; i < 2; i++)
	{
		CHECK_AND_LOCK_MUTEX(update_thread_data[i].mutex);

		if (update_thread_data[i].running == 1)
		{
			update_thread_data[i].running = 2;
		}

		CHECK_AND_UNLOCK_MUTEX(update_thread_data[i].mutex);

		SDL_CondSignal(update_thread_data[i].condition);
	}
}
コード例 #13
0
static void clear_zip(el_zip_file_t* zip)
{
	Uint32 i;

	if (zip == 0)
	{
		LOG_ERROR("Invalid zip");

		return;
	}

	CHECK_AND_LOCK_MUTEX(zip->mutex);

	LOG_DEBUG("Clearing zip file '%s'", zip->file_name);

	for (i = 0; i < zip->count; i++)
	{
		free(zip->files[i].file_name);
	}

	if (zip->files != 0)
	{
		free(zip->files);
	}

	if (zip->file_name != 0)
	{
		free(zip->file_name);
	}

	if (zip->file != 0)
	{
		unzClose(zip->file);
	}

	zip->file = 0;
	zip->count = 0;
	zip->files = 0;
	zip->file_name = 0;

	CHECK_AND_UNLOCK_MUTEX(zip->mutex);
}
コード例 #14
0
ファイル: update.c プロジェクト: gregoryfenton/other-life
void add_to_download(const char *filename, const Uint8 *md5)
{
	// lock the mutex
	CHECK_AND_LOCK_MUTEX(download_mutex);
	if(download_queue_size < MAX_UPDATE_QUEUE_SIZE){
		// add the file to the list, and increase the count
		download_queue[download_queue_size]= strdup(filename);
		download_MD5s[download_queue_size]= calloc(1, 16);
		memcpy(download_MD5s[download_queue_size], md5, 16);
		download_queue_size++;
		
		// start a thread if one isn't running
		if(!download_cur_file){
			char	buffer[1024];
			FILE    *fp;

			safe_snprintf(download_temp_file, sizeof(download_temp_file), "tmp/temp%03d.dat", ++temp_counter);
			buffer[sizeof(buffer)-1]= '\0';
			fp = open_file_config(download_temp_file, "wb+");
			if(fp == NULL){
				LOG_ERROR("%s: %s \"%s\": %s\n", reg_error_str, cant_open_file, download_temp_file, strerror(errno));
			} else {
				// build the proper URL to download
				download_cur_file= download_queue[--download_queue_size];
				download_cur_md5= download_MD5s[download_queue_size];
				if(is_this_files_lst){
					safe_snprintf(buffer, sizeof(buffer), "http://%s/updates%d%d%d/%s", update_server, VER_MAJOR, VER_MINOR, VER_RELEASE, download_cur_file);
				} else {
					safe_snprintf(buffer, sizeof(buffer), "http://%s/updates/%s", update_server, download_cur_file);
				}
				buffer[sizeof(buffer)-1]= '\0';
				LOG_DEBUG("@@ %s %s",update_server,buffer);
				http_threaded_get_file(update_server, buffer, fp, download_cur_md5, EVENT_DOWNLOAD_COMPLETE);
			}
		}
	}
	// unlock the mutex
	CHECK_AND_UNLOCK_MUTEX(download_mutex);
}
コード例 #15
0
void stopp_custom_update()
{
	Uint32 i;
	int result;

	for (i = 0; i < 2; i++)
	{
		CHECK_AND_LOCK_MUTEX(update_thread_data[i].mutex);

		update_thread_data[i].running = 0;

		CHECK_AND_UNLOCK_MUTEX(update_thread_data[i].mutex);

		SDL_CondSignal(update_thread_data[i].condition);
		SDL_WaitThread(update_thread_data[i].thread, &result);

		SDL_DestroyCond(update_thread_data[i].condition);
		SDL_DestroyMutex(update_thread_data[i].mutex);

		update_thread_data[i].mutex = 0;
		update_thread_data[i].thread = 0;
	}
}
コード例 #16
0
void clear_zip_archives()
{
	Uint32 i;

	ENTER_DEBUG_MARK("unload zips");

	CHECK_AND_LOCK_MUTEX(zip_mutex);

	for (i = 0; i < MAX_NUM_ZIP_FILES; i++)
	{
		clear_zip(&zip_files[i]);

		SDL_DestroyMutex(zip_files[i].mutex);
	}

	num_zip_files = 0;

	CHECK_AND_UNLOCK_MUTEX(zip_mutex);

	SDL_DestroyMutex(zip_mutex);

	LEAVE_DEBUG_MARK("unload zips");
}
コード例 #17
0
int command_update_status(char *text, int len)
{
	Uint32 i;

	if (custom_update == 0)
	{
		LOG_TO_CONSOLE(c_red1, "Custom updates disabled");

		return 1;
	}

	for (i = 0; i < 2; i++)
	{
		CHECK_AND_LOCK_MUTEX(update_thread_data[i].mutex);

		switch (update_thread_data[i].error)
		{
			case 0:
				LOG_TO_CONSOLE(c_green1,
					update_thread_data[i].str);
				break;
			case 1:
				LOG_TO_CONSOLE(c_orange1,
					update_thread_data[i].str);
				break;
			default:
				LOG_TO_CONSOLE(c_red1,
					update_thread_data[i].str);
				break;
		}

		CHECK_AND_UNLOCK_MUTEX(update_thread_data[i].mutex);
	}

	return 1;
}
コード例 #18
0
ファイル: new_update.c プロジェクト: MerkeX/Eternal-Lands
static void wait_for_threads(download_files_thread_data_t *data, Uint32* error)
{
	Sint32 result;
	Uint32 i;

	CHECK_AND_LOCK_MUTEX(data->mutex);

	if (*error == 0)
	{
		data->running = 2;
	}
	else
	{
		data->running = 0;
	}

	CHECK_AND_UNLOCK_MUTEX(data->mutex);

	for (i = 0; i < UPDATE_DOWNLOAD_THREAD_COUNT; i++)
	{
		SDL_CondBroadcast(data->condition);
		SDL_WaitThread(data->threads[i], &result);

		if (*error == 0)
		{
			*error = result;
		}
	}

	SDL_DestroyMutex(data->mutex);
	SDL_DestroyCond(data->condition);

	while (queue_pop(data->files) != 0);

	queue_destroy(data->files);
}
コード例 #19
0
ファイル: queue.c プロジェクト: sorlok/Eternal-Lands
int queue_push_signal(queue_t *queue, void *item)
{
	node_t *node;

	if (queue == 0)
	{
		return 0;
	}

	node = malloc(sizeof(node_t));

	if (node == 0)
	{
		CHECK_AND_UNLOCK_MUTEX(queue->mutex);

		LOG_ERROR("Failed to allocate memory for queue");

		return 0;
	}

	node->data = item;
	node->next = 0;

	/* Add to the end of the queue */
	CHECK_AND_LOCK_MUTEX(queue->mutex);

	queue->rear->next = node;
	queue->rear = node;
	queue->nodes++;

	CHECK_AND_UNLOCK_MUTEX(queue->mutex);

	SDL_CondSignal(queue->condition);

	return 1;
}
コード例 #20
0
void load_zip_archive(const char* file_name)
{
	unzFile file;
	unz_file_info64 info;
	unz_global_info64 global_info;
	el_zip_file_entry_t* files;
	char* name;
	Uint32 i, count, size, index;

	if (file_name == 0)
	{
		LOG_ERROR("Empty zip file name", file_name);

		return;
	}

	if (num_zip_files >= MAX_NUM_ZIP_FILES)
	{
		LOG_ERROR("Can't add zip file %s", file_name);

		return;
	}

	file = unzOpen64(file_name);

	if (unzGetGlobalInfo64(file, &global_info) != UNZ_OK)
	{
		LOG_ERROR("Can't load zip file %s", file_name);

		unzClose(file);

		return;
	}

	count = global_info.number_entry;

	if (unzGoToFirstFile(file) != UNZ_OK)
	{
		LOG_ERROR("Can't load zip file %s", file_name);

		unzClose(file);

		return;
	}

	ENTER_DEBUG_MARK("load zip");

	LOG_DEBUG("Loading zip file '%s' with %d files", file_name, count);

	files = malloc(count * sizeof(el_zip_file_entry_t));

	for (i = 0; i < count; i++)
	{
		unzGetFilePos64(file, &files[i].position);

		unzGetCurrentFileInfo64(file, &info, 0, 0, 0, 0, 0, 0);

		size = info.size_filename;

		files[i].file_name = calloc(size + 1, 1);

		unzGetCurrentFileInfo64(file, 0, files[i].file_name, size,
			0, 0, 0, 0);

		LOG_DEBUG("Loading file (%d) '%s' from zip file '%s'.", i,
			files[i].file_name, file_name);

		files[i].hash = mem_hash(files[i].file_name, size);

		unzGoToNextFile(file);
	}

	size = strlen(file_name);
	name = calloc(size + 1, 1);
	memcpy(name, file_name, size);

	LOG_DEBUG("Sorting files from zip file '%s'.", file_name);

	qsort(files, count, sizeof(el_zip_file_entry_t),
		compare_el_zip_file_entry);

	CHECK_AND_LOCK_MUTEX(zip_mutex);

	index = num_zip_files;

	for (i = 0; i < num_zip_files; i++)
	{
		if (zip_files[i].file_name == 0)
		{
			index = i;

			break;
		}
	}

	num_zip_files = max2u(num_zip_files, index + 1);

	CHECK_AND_LOCK_MUTEX(zip_files[index].mutex);

	CHECK_AND_UNLOCK_MUTEX(zip_mutex);

	LOG_DEBUG("Adding zip file '%s' at position %d.", file_name, index);

	zip_files[index].file_name = name;
	zip_files[index].file = file;
	zip_files[index].files = files;
	zip_files[index].count = count;

	CHECK_AND_UNLOCK_MUTEX(zip_files[index].mutex);

	LEAVE_DEBUG_MARK("load zip");

	LOG_DEBUG("Loaded zip file '%s' with %d files", file_name, count);
}
コード例 #21
0
ファイル: update.c プロジェクト: gregoryfenton/other-life
// finish up on one file that just downloaded
void    handle_file_download(struct http_get_struct *get)
{
	int sts;

	if(!get){   // huh? what are you doing?
		return;
	}
	
	// lock the mutex
	CHECK_AND_LOCK_MUTEX(download_mutex);
	if(get->status == 0){
		// replace the current file (creates all required directories)
		sts = move_file_to_updates(download_temp_file, download_cur_file, doing_custom);
 		LOG_DEBUG("Moved \"%s\" to \"%s\"", download_temp_file, download_cur_file);
		// check for errors
		if(!sts){
			// TODO: make the restart more intelligent
			if(allow_restart){
				if(strstr(download_cur_file, "2dobjects/")==NULL && strstr(download_cur_file, "3dobjects/")==NULL && strstr(download_cur_file, "maps/")==NULL && strstr(download_cur_file, "music/")==NULL && strstr(download_cur_file, "textures/")==NULL && strstr(download_cur_file, ".menu")==NULL)
					restart_required++;
				if(strstr(download_cur_file, ".menu") > 0)
					reload_user_menus();
				if(restart_required == 1)
				{
					LOG_TO_CONSOLE(c_red1, "Downloading Updates...");
				}
			}
		} else {
			LOG_ERROR("Unable to finish processing of %s (%d)", download_cur_file, errno);
			// the final renamed failed, no restart permitted
			allow_restart= 0;
			restart_required= 0;
		}
	} else {
		// and make sure we can't restart since we had a total failure
		allow_restart= 0;
		restart_required= 0;
	}

	// wait for the just completed thread so we free it's resources
	assert(get->thread_index<MAX_THREADS);
	SDL_WaitThread(thread_list[get->thread_index], NULL);
	thread_list[get->thread_index] = NULL;

	// release the filename
	free(download_cur_file);
	free(download_cur_md5);
	download_cur_file= NULL;

	// unlock mutex
	CHECK_AND_UNLOCK_MUTEX(download_mutex);

	// now, release everything
	free(get);
	
	// lock the mutex
	CHECK_AND_LOCK_MUTEX(download_mutex);
	if(download_queue_size > 0 && !download_cur_file){
		// start a thread if a file is waiting to download and no download active
		char	buffer[512];
		FILE    *fp;

		safe_snprintf(download_temp_file, sizeof(download_temp_file), "tmp/temp%03d.dat", ++temp_counter);
		fp = open_file_config(download_temp_file, "wb+");
		if(fp == NULL){
			LOG_ERROR("%s: %s \"%s\": %s\n", reg_error_str, cant_open_file, download_temp_file, strerror(errno));
		} else {
			// build the proper URL to download
			download_cur_file= download_queue[--download_queue_size];
			download_cur_md5= download_MD5s[download_queue_size];
			if(is_this_files_lst) {
				safe_snprintf(buffer, sizeof(buffer), "http://%s/updates%d%d%d/%s", update_server, VER_MAJOR, VER_MINOR, VER_RELEASE, download_cur_file);
			} else {
				safe_snprintf(buffer, sizeof(buffer), "http://%s/updates/%s", update_server, download_cur_file);
			}
			buffer[sizeof(buffer)-1]= '\0';
			http_threaded_get_file(update_server, buffer, fp, download_cur_md5, EVENT_DOWNLOAD_COMPLETE);
		}
	}

	// check to see if this was the last file && a restart is required
	if(!update_busy && restart_required && allow_restart && download_queue_size <= 0 && !download_cur_file){
		// yes, now trigger a restart
		LOG_INFO("Restart required because of update");
		// Display something on the screen for a little bit before restarting
		if(autoupdate_delay >= 0)
		{
			int i;
			for (i=0; i < windows_list.num_windows;i++)
			{
				if(get_show_window(i))
					break;
			}
			create_update_root_window (window_width, window_height, autoupdate_delay, i);
			show_window (update_root_win);
		} else {
			LOG_TO_CONSOLE(c_red2, "You need to restart the client to activate the updates!");
		}
	}

	// unlock mutex
	CHECK_AND_UNLOCK_MUTEX(download_mutex);
}
コード例 #22
0
ファイル: new_update.c プロジェクト: MerkeX/Eternal-Lands
static int download_files_thread(void* _data)
{
	char file_name[256];
	char comment[64];
	download_files_thread_data_t *data = NULL;
	update_info_t* info = NULL;
	char* download_buffer = NULL;
	void* file_buffer = NULL;
	FILE *file = NULL;
	Uint64 file_size, size;
	Uint32 i, len, result, error, count, index, running;
	Uint32 download_buffer_size;

	data = (download_files_thread_data_t*)_data;

	init_thread_log("download_files");

#ifdef WINDOWS
	file = my_tmpfile();
#else
	file = tmpfile();
#endif

	if (file == 0)
	{
		return 1;
	}

	error = 0;
	file_buffer = 0;
	download_buffer_size = 4096;
	download_buffer = calloc(download_buffer_size, sizeof(char));
	count = data->count;

	while (1)
	{
		CHECK_AND_LOCK_MUTEX(data->mutex);

		do
		{
			info = queue_pop(data->files);

			running = data->running;

			if ((running == 1) && (info == 0))
			{
				SDL_CondWait(data->condition, data->mutex);
			}
		}
		while ((data->running == 1) && (info == 0));

		index = data->index;

		CHECK_AND_UNLOCK_MUTEX(data->mutex);

		if (info == 0)
		{
			break;
		}

		if (data->update_progress_function("Downloading files", count,
			index, data->user_data) != 1)
		{
			CHECK_AND_LOCK_MUTEX(data->mutex);

			data->running = 0;

			CHECK_AND_UNLOCK_MUTEX(data->mutex);

			error = 2;

			break;
		}

		for (i = 0; i < 5; i++)
		{
			fseek(file, 0, SEEK_SET);

			result = download_file(info->file_name, file,
				data->server, data->path, &size,
				download_buffer_size,
				download_buffer, 0, 0);

			if (result != 0)
			{
				LOG_ERROR("Download error %d while updating "
					"file '%s' from server '%s', retrying"
					" it", result, info->file_name,
					data->server);

				error = 3;
				continue;
			}

			if (file_read(file, size, &file_buffer, &file_size) !=
				0)
			{
				LOG_ERROR("Read error while updating file '%s' "
					"from server '%s', retrying it",
					info->file_name, data->server);

				error = 3;
				continue;
			}

			convert_md5_digest_to_comment_string(info->digest,
				sizeof(comment), comment);

			len = strlen(info->file_name);

			safe_snprintf(file_name, sizeof(file_name), "%s",
				info->file_name);

			if (has_suffix(file_name, len, ".xz", 3))
			{
				file_name[len - 3] = 0;
			}

			CHECK_AND_LOCK_MUTEX(data->mutex);

			add_to_zip(file_name, file_size, file_buffer,
				data->dest, comment);
			data->index++;

			CHECK_AND_UNLOCK_MUTEX(data->mutex);

			free(file_buffer);

			error = 0;
			break;
		}

		if (error != 0)
		{
			break;
		}
	}

	free(download_buffer);

	fclose(file);

	return error;
}
コード例 #23
0
ファイル: new_update.c プロジェクト: MerkeX/Eternal-Lands
static Uint32 download_files(update_info_t* infos, const Uint32 count,
	const char* server, const char* path, const Uint32 source_count,
	unzFile* sources, zipFile dest, progress_fnc update_progress_function,
	void* user_data)
{
	char file_name[256];
	download_files_thread_data_t thread_data;
	FILE *file;
	Uint64 len;
	Uint32 i, j, download, error, index;

#ifdef WINDOWS
	file = my_tmpfile();
#else
	file = tmpfile();
#endif

	if (file == 0)
	{
		return 1;
	}

	error = 0;

	init_threads(&thread_data, count, server, path, dest,
		update_progress_function, user_data);

	for (i = 0; i < count; i++)
	{
		CHECK_AND_LOCK_MUTEX(thread_data.mutex);

		index = thread_data.index;

		CHECK_AND_UNLOCK_MUTEX(thread_data.mutex);

		if (update_progress_function("Updating files", count, index,
			user_data) != 1)
		{
			error = 2;

			break;
		}

		download = 1;

		len = strlen(infos[i].file_name);

		safe_snprintf(file_name, sizeof(file_name), "%s",
			infos[i].file_name);

		if (has_suffix(file_name, len, ".xz", 3))
		{
			file_name[len - 3] = 0;
		}

		for (j = 0; j < source_count; j++)
		{
			if (check_md5_from_zip(sources[j], file_name,
				infos[i].digest) == 0)
			{
				CHECK_AND_LOCK_MUTEX(thread_data.mutex);

				copy_from_zip(sources[j], dest);
				thread_data.index++;

				CHECK_AND_UNLOCK_MUTEX(thread_data.mutex);

				download = 0;

				break;
			}
		}

		if (download == 1)
		{
			queue_push(thread_data.files, &infos[i]);
			SDL_CondSignal(thread_data.condition);
		}
	}

	wait_for_threads(&thread_data, &error);

	fclose(file);

	return error;
}