[axel-commits] r80 - in /branches/3.x-broken: doc/CHANGES doc/ROADMAP src/axel.c src/axel.h src/conf.h src/conn.c src/messages.c src/messages.h

phihag-guest at users.alioth.debian.org phihag-guest at users.alioth.debian.org
Sat Jan 3 07:54:11 UTC 2009


Author: phihag-guest
Date: Sat Jan  3 07:54:10 2009
New Revision: 80

URL: http://svn.debian.org/wsvn/axel/?sc=1&rev=80
Log:
Finalize messaging (for now)
fill in some blanks for axel_*


Modified:
    branches/3.x-broken/doc/CHANGES
    branches/3.x-broken/doc/ROADMAP
    branches/3.x-broken/src/axel.c
    branches/3.x-broken/src/axel.h
    branches/3.x-broken/src/conf.h
    branches/3.x-broken/src/conn.c
    branches/3.x-broken/src/messages.c
    branches/3.x-broken/src/messages.h

Modified: branches/3.x-broken/doc/CHANGES
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/doc/CHANGES?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/doc/CHANGES (original)
+++ branches/3.x-broken/doc/CHANGES Sat Jan  3 07:54:10 2009
@@ -21,12 +21,9 @@
 - Moved includes of standard libraries to libs.h to reduce size of axel.h 
 - Use AXEL_SIZE for all file size variables
 
-- Temporarily thrown out: ftp, search
-
-Version 2.3:
-
-- Wait for thread termination in axel.c:axel_do (Closes: #311255), thanks John Ripa
-- New Chinese translation and manpage, thanks Shuge Lee
+- Temporarily thrown out: ftp, search, speed limit
+
+TODO: COPY CHANGELOG FROM trunk/ here
 
 Version 2.2:
 

Modified: branches/3.x-broken/doc/ROADMAP
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/doc/ROADMAP?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/doc/ROADMAP (original)
+++ branches/3.x-broken/doc/ROADMAP Sat Jan  3 07:54:10 2009
@@ -18,7 +18,6 @@
 * Do not rerequest HTTP code  != 20x more than once
 * Exponential backoff, exponential backoff, and make sure to include exponential backoff
 * re-add proxy support
-
 
 Code structure
 ==============
@@ -56,7 +55,7 @@
 Remove all TODOs
 
 Fix/test/simplify i18n regeneration (paths!) (remove .SUFFIXES?)
-Check speed limit
+Reintroduce speed limit
 Check on BSD, Mac OS X, Cygwin
 
 (User) Documentation

Modified: branches/3.x-broken/src/axel.c
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/src/axel.c?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/src/axel.c (original)
+++ branches/3.x-broken/src/axel.c Sat Jan  3 07:54:10 2009
@@ -26,11 +26,18 @@
 #include "axel.h"
 
 static void axel_prepare(axel_t* axel);
+static void axel_do(axel_t* axel);
+static void axel_openoutfile(axel_t* axel, char* filename);
+
+static void axel_startthread(conn_t* conn);
+
 static void axel_teardown(axel_t* axel);
-static void axel_save_state(axel_t* axel);
+
 static void axel_set_state(axel_t* axel, int state);
+static void axel_message_now(const axel_t* axel, const axel_message_t* msg);
 static void axel_update_display(const axel_t* axel);
-static void axel_startthread(conn_t* conn);
+
+
 
 /**
 * Add a URL. urlstr is a pointer to a string specified by the user
@@ -98,24 +105,9 @@
 int axel_download(axel_t* axel) {
 	axel_prepare(axel);
 	
-	if (axel->state != AXEL_STATE_DOWNLOADING) {
-		axel_set_state(axel, AXEL_STATE_ERROR);
-		
-		return axel->state;
-	}
-	
-
-	for (int cid = 0;;cid = (cid < axel->conncount) ? cid + 1 : 0) {
-		// Main loop, visit all connections
-		
-		
-		
-		
-	}
-	
-	
-	// TODO set state to finished if not erred
-	
+	while (axel->state == AXEL_STATE_DOWNLOADING) {
+		axel_do(axel);
+	}
 	
 	return axel->state;
 }
@@ -127,27 +119,83 @@
 	// TODO Determine file name
 	// TODO determine file size
 	
-	
-	if (axel->filename == NULL) {
-		axel->filename = safe_strdup(axel->conf->default_filename);
-	}
-	
-	// TODO Open outfile
-	
-	
-	// Determine state file name
-	const size_t SUFFIXLEN = strlen(STATEFILE_SUFFIX);
-	size_t fnlen = strlen(axel->filename);
-	axel->statefilename = malloc(fnlen + SUFFIXLEN + 1);
-	memcpy(axel->statefilename + fnlen, STATEFILE_SUFFIX, SUFFIXLEN);
-	axel->statefilename[fnlen + SUFFIXLEN + SUFFIXLEN] = '\0';
-	
 	// Start counting time
 	axel->start_utime = getutime();
 	axel_set_state(axel, AXEL_STATE_DOWNLOADING);
 	
 	// TODO set conncount according to conf
-	// TODO start threads
+}
+
+// An iteration of axel's main loop
+void axel_do(axel_t* axel) {
+	fd_set fds[1];
+	
+	// Assemble possibly ready descriptors
+	FD_ZERO(fds);
+	int hifd = 0;
+	for (i = 0;i < axel->conf->num_connections;i++) {
+		if (axel->conn[i].cstate == downloading) {
+			FD_SET(axel->conn[i].fd, fds);
+		}
+		
+		hifd = max(hifd, axel->conn[i].fd);
+	}
+	
+	if (hifd == 0) { // No connections yet.
+		usleep (100000);
+		goto conn_check;
+	} else {
+		// TODO check this
+		
+		timeval->tv_sec = 0;
+		timeval->tv_usec = 100000;
+		
+		/* A select() error probably means it was interrupted
+		   by a signal, or that something else's very wrong...	*/
+		if (select(hifd + 1, fds, NULL, NULL, timeval) == -1) {
+			axel_message_now(axel, critical, "select() call failed.");
+			axel_set_state(axel, AXEL_STATE_ERROR);
+			return;
+		}
+	}
+	
+	// Read and write data
+	for (int cid = 0;;cid = (cid < axel->conncount) ? cid + 1 : 0) {
+		if ((axel->conn[cid].state == downloading) && FD_ISSET(axel->conn[cid])) {
+			
+			
+			
+		}
+	}
+	
+	// TODO Write to statefile if necessary
+	
+	
+	// TODO set state to finished if not erred
+}
+
+static void axel_openoutfile(axel_t* axel, char* filename) {
+	if (filename == NULL) {
+		filename = safe_strdup(axel->conf->default_filename);
+	}
+	axel->filename = filename;
+	
+	// TODO Open outfile
+	
+	
+	// TODO check whether to create statefile
+	
+	if (axel->statefilename == NULL) { // Determine state file name
+		const size_t SUFFIXLEN = strlen(STATEFILE_SUFFIX);
+		size_t fnlen = strlen(filename);
+		axel->statefilename = safe_malloc(fnlen + SUFFIXLEN + 1);
+		memcpy(axel->statefilename, filename, fnlen);
+		memcpy(axel->statefilename + fnlen, STATEFILE_SUFFIX, SUFFIXLEN);
+		axel->statefilename[fnlen + SUFFIXLEN + SUFFIXLEN] = '\0';
+	}
+	
+	// TODO open state file
+	
 }
 
 /**
@@ -160,26 +208,41 @@
 	// TODO Close outfile
 }
 
-/**
-* Send a message from the main thread
-* @param message The message to send. Note that this must be freed by the caller
-*/
-void axel_message(const axel_t* axel, message_t* msg) {
-	message_t* msg = safe_malloc(sizeof(message_t));
-	
-	msg->
-	
-	axel_message(axel, msg);
-}
-
-/**
-* @param message The message, will be freed by this method
-*/
-void axel_message_detail(const axel_t* axel, int verbosity, char* message, _Bool msgOnHeap) {
-	
-}
-
-void axel_message_fmt(const axel_t *axel, int verbosity, const char *format, ...) {
+static void axel_update_display(const axel_t* axel) {
+	if (axel->display_handler != NULL) {
+		axel->display_handler(axel);
+	}
+}
+
+static void axel_set_state(axel_t* axel, int state) {
+	axel->state = state;
+	axel_update_display();
+}
+
+// Start a new thread that immediately executes afterwards.
+_Bool axel_startthread(conn_t* c) {
+	if (pthread_create(conn->thread, NULL, conn_threadstart, c) != 0) {
+		axel_message_now(conn->axel, critical, _("Thread creation failed"));
+		return false;
+	}
+	
+	return true;
+}
+
+
+
+
+/* Messages */
+
+void axel_message_static(axel_t* axel, message_relevance rel, const char* msgstr) {
+	axel_message(axel, message_new_safe(rel, msgstr, false));
+}
+
+void axel_message_heap(axel_t* axel, message_relevance rel, char* msgstr) {
+	axel_message(axel, message_new_safe(rel, msgstr, true));
+}
+
+void axel_message_fmt(axel_t *axel, message_relevance rel, const char *format, ...) {
 	const MAX_MSG_SIZE = 1024;
 	char* buf = malloc(MAX_MSG_SIZE);
 	
@@ -191,38 +254,52 @@
 	axel_message_heap(axel, verbosity, buf);
 }
 
+// Send a message from any thread
+void axel_message(axel_t* axel, message_t* msg) {
+	// We don't want to be interrupted
+	int oldstate;
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
+	
+	{
+		pthread_mutex_lock(axel->msgmtx);
+		
+		msgq_enqueue(axel->msgs, msg);
+		
+		pthread_mutex_unlock(axel->msgmtx);
+	}
+	
+	pthread_setcancelstate(oldstate, NULL);
+}
+
+void axel_print_messages(const axel_t* axel) {
+	message_t* msg;
+	while (1) {
+		pthread_mutex_lock(axel->msgmtx);
+		
+		msg = msgq_dequeue(axel->msgs);
+		
+		pthread_mutex_unlock(axel->msgmtx);
+		
+		// Got all messages
+		if (msg == NULL) {
+			break;
+		}
+		
+		axel_message_now(axel, msg->rel, msg->str);
+		
+		message_free(msg);
+	}
+}
+
 /**
 * Display a message. Must only be called from the main thread.
 */
-void axel_message(const axel_t* axel, const axel_message_t* msg) {
+void axel_message_now(const axel_t* axel, message_relevance rel, const char* msg) {
 	if (axel->message_handler != NULL) {
-		axel->message_handler(axel, msg->verbosity, msg->message);
+		axel->message_handler(axel, rel, msg);
 	}
 	axel_update_display();
 }
-
-static void axel_update_display(const axel_t* axel) {
-	if (axel->display_handler != NULL) {
-		axel->display_handler(axel);
-	}
-}
-
-static void axel_set_state(axel_t* axel, int state) {
-	axel->state = state;
-	axel_update_display();
-}
-
-// Start a new thread that immediately executes afterwards.
-_Bool axel_startthread(conn_t* c) {
-	if (pthread_create(conn->thread, NULL, conn_threadstart, c) != 0) {
-		axel_message(conn->axel, critical, _("Thread creation failed"));
-		return false;
-	}
-	
-	return true;
-}
-
-
 
 
 

Modified: branches/3.x-broken/src/axel.h
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/src/axel.h?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/src/axel.h (original)
+++ branches/3.x-broken/src/axel.h Sat Jan  3 07:54:10 2009
@@ -86,12 +86,12 @@
 	/** A function that displays messages with the following parameters:
 	
 	axel: A pointer to the calling axel structure
-	verbosity: one of the VERBOSITY_* values
+	rel: Importance of this message, may be used to supress some
 	message: The message to display (already i18ned), will be freed upon returning
 	
 	NULL for no message display
 	*/
-	void (*message_handler)(const struct axel_struct* axel, int verbosity, const char* message);
+	void (*message_handler)(const struct axel_struct* axel, message_relevance rel, const char* message);
 	/**
 	* A handler that displays the current download state.
 	* May be called frequently. Is guaranteed to be called on state changes and messages.
@@ -118,11 +118,7 @@
 	AXEL_FILESIZE size; // The full file size in Byte, or AXEL_SIZE_UNDETERMINED if the file size is not yet determined or undeterminable
 	AXEL_TIME start_utime; // Start time in microseconds
 	
-	// The download's state, one of the AXEL_STATE_* constants
-	int state;
-	
-	// Time to wait because of speed limit.
-	int delay_time;
+	int state; // The download's state, one of the AXEL_STATE_* constants
 	
 	// Messages
 	message_queue_t msgs[1];
@@ -130,10 +126,15 @@
 };
 typedef struct axel_struct axel_t;
 
-// Main axel API: The following methods are used by the frontend.
+// Main axel API: The following methods form the axel API.
 void axel_init(axel_t* ax, const conf_t *conf);
 _Bool axel_addurlstr(axel_t* axel, const char* urlstr, int priority);
 axel_state axel_download(axel_t* axel);
 void axel_destroy(axel_t* axel);
 
-// For other functions called only from axel's core, see messages.h
+// Called from axel's core, but not the main thread
+void axel_message_static(axel_t* axel, message_relevance rel, const char* msgstr);
+void axel_message_heap(axel_t* axel, message_relevance rel, char* msgstr);
+void axel_message_fmt(axel_t *axel, message_relevance rel, const char *format, ... );
+void axel_message(axel_t* axel, message_t* msg);
+

Modified: branches/3.x-broken/src/conf.h
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/src/conf.h?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/src/conf.h (original)
+++ branches/3.x-broken/src/conf.h Sat Jan  3 07:54:10 2009
@@ -26,17 +26,14 @@
 typedef struct
 {
 	char* default_filename;
-	char* http_proxy; /* 0 for no proxy */
+	char* http_proxy; /* NULL for no proxy */
 	char** no_proxy; /* NULL-terminated list of no-proxy hosts */
-	int strip_cgi_parameters;
 	int save_state_interval;
 	int connection_timeout;
 	int reconnect_delay;
 	int num_connections;
 	int buffer_size;
 	int max_speed;
-	int verbose;
-	int alternate_output;
 	
 	char** interfaces;
 	
@@ -49,6 +46,13 @@
 	char** add_header;
 	
 	char* user_agent; // NULL for default
+	
+	// Interface options
+	int verbose;
+	int alternate_output;
+	
+	// TODO Check those
+	int strip_cgi_parameters;
 } conf_t;
 
 int conf_loadfile( conf_t *conf, char *file );

Modified: branches/3.x-broken/src/conn.c
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/src/conn.c?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/src/conn.c (original)
+++ branches/3.x-broken/src/conn.c Sat Jan  3 07:54:10 2009
@@ -39,17 +39,18 @@
 
 // Entry point for a created thread
 void conn_threadstart(void* conn_void) {
+	conn_t* conn = conn_void;
 	int oldstate; // Dummy
 	
 	if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate) != 0) ||
 		(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate) != 0)) {
 		
-		conn->message = safe_strdup("Thread initialization failed");
+		axel_message_static(conn->axel, "Thread initialization failed");
 		conn->cstate = ERROR;
 		return;
 	}
 	
-	conn_readheaders((conn_t*) conn_void);
+	conn_readheaders(conn);
 }
 
 // Reads all headers, blocks until read. cstate is guaranteed to be either DOWNLOADING or FINISHED afterwards.

Modified: branches/3.x-broken/src/messages.c
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/src/messages.c?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/src/messages.c (original)
+++ branches/3.x-broken/src/messages.c Sat Jan  3 07:54:10 2009
@@ -1,2 +1,57 @@
 /* Textual messages within axel */
 
+message_t* message_new_safe(char* str, _Bool onheap, message_relevance rel) {
+	message_t* res = malloc_safe(sizeof(message_t));
+	
+	res->str = str;
+	res->onheap = onheap;
+	res->rel = rel;
+	
+	return res;
+}
+
+void message_free(message_t* msg) {
+	if (msg->onheap) {
+		free(msg->str);
+	}
+	
+	free(msg);
+}
+
+void msgq_init(msgq_t* mq) {
+	msl->head = NULL;
+	msl->tail = NULL;
+}
+
+void msgq_destroy(msgq_t* mq) {
+	message_t* msg;
+	while ((msg = msgq_dequeue(msl)) != NULL) {
+		message_free(msg);
+	}
+}
+
+message_t* msgq_dequeue(msgq_t* mq) {
+	message_t* res = mq->head;
+	
+	if (res != NULL) {
+		mq->head = res->next;
+		
+		if (res->next == NULL) {
+			mq->tail = NULL;
+		}
+	}
+	
+	return res;
+}
+
+void msgq_enqueue(msgq_t* mq, message_t* msg) {
+	msg->next = NULL;
+	
+	if (mq->tail == NULL) {
+		mq->tail = msg;
+		mq->head = msg;
+	} else {
+		mq->tail->next = msg;
+		mq->tail = msg;
+	}
+}

Modified: branches/3.x-broken/src/messages.h
URL: http://svn.debian.org/wsvn/axel/branches/3.x-broken/src/messages.h?rev=80&op=diff
==============================================================================
--- branches/3.x-broken/src/messages.h (original)
+++ branches/3.x-broken/src/messages.h Sat Jan  3 07:54:10 2009
@@ -1,6 +1,7 @@
-/* Textual messages within axel */
+/* Store textual messages in axel */
 
 enum message_relevance {
+	debug,
 	chatter,
 	status,
 	warning,
@@ -9,16 +10,24 @@
 };
 
 struct {
-	char* msg; // The message text, on the heap.
-	_Bool onheap; // True iff the message is stored on the heap (and must be freed by this module)
+	char* str; // The message text, on the heap.
+	_Bool onheap; // True iff msg is stored on the heap (and must be freed by this module)
 	message_relevance rel;
 	struct message_struct* next;
 } message_struct;
-
 typedef struct message_struct message_t;
 
+void message_new_safe(message_t* msg, char* str, _Bool onheap, message_relevance rel);
+void message_free(message_t* msg);
 
-// These functions are only called from axel's core
-void axel_message(const axel_t* axel, int verbosity, const char* message);
-void axel_message_fmt(const axel_t *axel, int verbosity, const char *format, ... );
-void axel_message_heap(const axel_t* axel, int verbosity, const char* message);
+typedef struct {
+	message_t* head;
+	message_t* tail;
+} msgq_t;
+
+void msgq_init(msgq_t* mq);
+void msgq_destroy(msgq_t* mq);
+message_t* msgq_dequeue(msgq_t* mq);
+void msgq_enqueue(msgq_t* mq, message_t* msg);
+
+




More information about the axel-commits mailing list