[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