|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/client/htext.h b/src/plugins/apache-httpd/src/client/htext.h
|
|
Petr Vokac |
238799e |
index 1303e77e..853a146a 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/client/htext.h
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/client/htext.h
|
|
Petr Vokac |
238799e |
@@ -67,6 +67,8 @@ typedef enum
|
|
Petr Vokac |
238799e |
HTEXTOP_NOHEAD, /* Disable HEAD requests */
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
HTEXTOP_USE_COPY_FROM_SOURCE, /* Use Copy Source (fetching) instead of Copy Destination (pushing) */
|
|
Petr Vokac |
238799e |
+ HTEXTOP_COPY_DONE, /* If set, called after COPY operation is done */
|
|
Petr Vokac |
238799e |
+ HTEXTOP_COPY_DONE_DATA, /* Additional data to pass to transfer done function */
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
HTEXTOP_SENTINEL, /* To mark the last one */
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/client/htext_api.c b/src/plugins/apache-httpd/src/client/htext_api.c
|
|
Petr Vokac |
238799e |
index 1c3df75c..201a5e37 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/client/htext_api.c
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/client/htext_api.c
|
|
Petr Vokac |
238799e |
@@ -92,6 +92,8 @@ static option_entry option_definitions[] = {
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
{ OT_INT, (option_value) 0 }, /* HTEXTOP_NOHEAD */
|
|
Petr Vokac |
238799e |
{ OT_INT, (option_value) 0 }, /* HTEXTOP_USE_COPY_FROM_SOURCE */
|
|
Petr Vokac |
238799e |
+ { OT_POINTER, (option_value) NULL }, /* HTEXTOP_COPY_DONE */
|
|
Petr Vokac |
238799e |
+ { OT_POINTER, (option_value) NULL }, /* HTEXTOP_COPY_DONE_DATA */
|
|
Petr Vokac |
238799e |
};
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
/**
|
|
Petr Vokac |
238799e |
@@ -156,6 +158,10 @@ void htext_destroy(htext_handle *handle)
|
|
Petr Vokac |
238799e |
free(handle->error_string);
|
|
Petr Vokac |
238799e |
free(handle->partial_total);
|
|
Petr Vokac |
238799e |
free(handle->partial_done);
|
|
Petr Vokac |
238799e |
+ for (i = 0; i < handle->partials; ++i) {
|
|
Petr Vokac |
238799e |
+ free(handle->partial_rconn[i]);
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ free(handle->partial_rconn);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
for (i = 0; i < HTEXTOP_SENTINEL; ++i) {
|
|
Petr Vokac |
238799e |
if (handle->options[i].type == OT_STRING)
|
|
Petr Vokac |
238799e |
@@ -249,6 +255,7 @@ int htext_perform(htext_handle *handle)
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
void* (*performer)(void *);
|
|
Petr Vokac |
238799e |
const char *performer_str;
|
|
Petr Vokac |
238799e |
+ int i;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
/* Check status */
|
|
Petr Vokac |
238799e |
switch (handle->status) {
|
|
Petr Vokac |
238799e |
@@ -263,9 +270,14 @@ int htext_perform(htext_handle *handle)
|
|
Petr Vokac |
238799e |
free(handle->error_string);
|
|
Petr Vokac |
238799e |
free(handle->partial_total);
|
|
Petr Vokac |
238799e |
free(handle->partial_done);
|
|
Petr Vokac |
238799e |
+ for (i = 0; i < handle->partials; ++i) {
|
|
Petr Vokac |
238799e |
+ free(handle->partial_rconn[i]);
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ free(handle->partial_rconn);
|
|
Petr Vokac |
238799e |
handle->error_string = NULL;
|
|
Petr Vokac |
238799e |
handle->partial_done = NULL;
|
|
Petr Vokac |
238799e |
handle->partial_total = NULL;
|
|
Petr Vokac |
238799e |
+ handle->partial_rconn = NULL;
|
|
Petr Vokac |
238799e |
handle->partials = 0;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
/* Check we have source and destination */
|
|
Petr Vokac |
238799e |
@@ -326,7 +338,9 @@ int htext_perform(htext_handle *handle)
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
void htext_abort(htext_handle *handle)
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
- /* TODO: Really abort */
|
|
Petr Vokac |
238799e |
+ /* TODO: Transfer is aborted by returning non-zero value from progress
|
|
Petr Vokac |
238799e |
+ function (this doesn't happen immediately and with curl easy interface
|
|
Petr Vokac |
238799e |
+ there is no better option except closing directly transfer socket) */
|
|
Petr Vokac |
238799e |
handle->status = HTEXTS_ABORTED;
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/client/htext_common.c b/src/plugins/apache-httpd/src/client/htext_common.c
|
|
Petr Vokac |
238799e |
index 34a28353..219988dc 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/client/htext_common.c
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/client/htext_common.c
|
|
Petr Vokac |
238799e |
@@ -40,8 +40,6 @@ void htext_partial_clean(htext_chunk *p)
|
|
Petr Vokac |
238799e |
curl_easy_cleanup(p->curl);
|
|
Petr Vokac |
238799e |
if (p->fd)
|
|
Petr Vokac |
238799e |
GETIO(p->handle) ->close(p->fd);
|
|
Petr Vokac |
238799e |
- if (p->chunk_rconn && *(p->chunk_rconn))
|
|
Petr Vokac |
238799e |
- free(*(p->chunk_rconn));
|
|
Petr Vokac |
238799e |
if (p->error_string)
|
|
Petr Vokac |
238799e |
free(p->error_string);
|
|
Petr Vokac |
238799e |
if (p->http_response)
|
|
Petr Vokac |
238799e |
@@ -219,28 +217,37 @@ int htext_progress_callback(void *pp, curl_off_t dltotal, curl_off_t dlnow,
|
|
Petr Vokac |
238799e |
*(partial->chunk_done) = dlnow;
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
- CURLcode res = CURLE_OK;
|
|
Petr Vokac |
238799e |
- char *ip = NULL;
|
|
Petr Vokac |
238799e |
- long port = 0;
|
|
Petr Vokac |
238799e |
-
|
|
Petr Vokac |
238799e |
- if (res == CURLE_OK)
|
|
Petr Vokac |
238799e |
- res = curl_easy_getinfo(partial->curl, CURLINFO_PRIMARY_IP, &ip);
|
|
Petr Vokac |
238799e |
- if (res == CURLE_OK)
|
|
Petr Vokac |
238799e |
- res = curl_easy_getinfo(partial->curl, CURLINFO_PRIMARY_PORT, &port);
|
|
Petr Vokac |
238799e |
- if (res == CURLE_OK && ip) {
|
|
Petr Vokac |
238799e |
- int len = strlen(ip)+15;
|
|
Petr Vokac |
238799e |
- char *rconn = malloc(len);
|
|
Petr Vokac |
238799e |
- if (strchr(ip, ':')) {
|
|
Petr Vokac |
238799e |
- snprintf(rconn, len, "tcp:[%s]:%ld", ip, port);
|
|
Petr Vokac |
238799e |
- } else {
|
|
Petr Vokac |
238799e |
- snprintf(rconn, len, "tcp:%s:%ld", ip, port);
|
|
Petr Vokac |
238799e |
+ /* Add remote connection only after real data transfer starts
|
|
Petr Vokac |
238799e |
+ otherwise ip:port info could come previous (headnode) connection */
|
|
Petr Vokac |
238799e |
+ if (dltotal > 0 || dlnow > 0 || ultotal > 0 || ulnow > 0) {
|
|
Petr Vokac |
238799e |
+ CURLcode res = CURLE_OK;
|
|
Petr Vokac |
238799e |
+ char *ip = NULL;
|
|
Petr Vokac |
238799e |
+ long port = 0;
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ if (res == CURLE_OK)
|
|
Petr Vokac |
238799e |
+ res = curl_easy_getinfo(partial->curl, CURLINFO_PRIMARY_IP, &ip);
|
|
Petr Vokac |
238799e |
+ if (res == CURLE_OK)
|
|
Petr Vokac |
238799e |
+ res = curl_easy_getinfo(partial->curl, CURLINFO_PRIMARY_PORT, &port);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ if (res == CURLE_OK && ip && port) {
|
|
Petr Vokac |
238799e |
+ char rconn[HTEXT_PERF_MARKER_MAX_RCONN_SIZE];
|
|
Petr Vokac |
238799e |
+ if (strchr(ip, ':')) {
|
|
Petr Vokac |
238799e |
+ snprintf(rconn, sizeof(rconn), "tcp:[%s]:%ld", ip, port);
|
|
Petr Vokac |
238799e |
+ } else {
|
|
Petr Vokac |
238799e |
+ snprintf(rconn, sizeof(rconn), "tcp:%s:%ld", ip, port);
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ htext_log(partial->handle, "connection %s, download %ld/%ld, upload %ld/%ld", rconn, dlnow, dltotal, ulnow, ultotal);
|
|
Petr Vokac |
238799e |
+ if (!*(partial->chunk_rconn))
|
|
Petr Vokac |
238799e |
+ *(partial->chunk_rconn) = calloc(sizeof(char), HTEXT_PERF_MARKER_MAX_RCONN_SIZE);
|
|
Petr Vokac |
238799e |
+ if (strcmp(*(partial->chunk_rconn), rconn))
|
|
Petr Vokac |
238799e |
+ strcpy(*(partial->chunk_rconn), rconn);
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
- htext_log(partial->handle, "connection %s, download %ld/%ld, upload %ld/%ld", rconn, dlnow, dltotal, ulnow, ultotal);
|
|
Petr Vokac |
238799e |
- char *tmp = *(partial->chunk_rconn);
|
|
Petr Vokac |
238799e |
- *(partial->chunk_rconn) = rconn;
|
|
Petr Vokac |
238799e |
- if (tmp) free(tmp);
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
+ /* Let curl abort terminated transfer (doesn't happen immediately) */
|
|
Petr Vokac |
238799e |
+ if (partial->handle->status == HTEXTS_ABORTED)
|
|
Petr Vokac |
238799e |
+ return 1;
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
return 0;
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/client/htext_copy.c b/src/plugins/apache-httpd/src/client/htext_copy.c
|
|
Petr Vokac |
238799e |
index 88c4aacd..0be2f969 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/client/htext_copy.c
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/client/htext_copy.c
|
|
Petr Vokac |
238799e |
@@ -83,6 +83,7 @@ static size_t htext_copy_write_callback(char *buffer, size_t size, size_t nmemb,
|
|
Petr Vokac |
238799e |
memset(perf_data, 0, sizeof(*perf_data));
|
|
Petr Vokac |
238799e |
perf_data->index = -1;
|
|
Petr Vokac |
238799e |
perf_data->transferred = -1;
|
|
Petr Vokac |
238799e |
+ perf_data->rconn[0] = '\0';
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
else if (strncasecmp("Timestamp:", p, 10) == 0)
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
@@ -94,15 +95,17 @@ static size_t htext_copy_write_callback(char *buffer, size_t size, size_t nmemb,
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
else if (strncasecmp("Stripe Bytes Transferred:", p, 25) == 0)
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
- perf_data->transferred = atol(p + 26);
|
|
Petr Vokac |
238799e |
+ perf_data->transferred = atol(p + 25);
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
else if (strncasecmp("Total Stripe Count:", p, 19) == 0)
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
- perf_data->count = atoi(p + 20);
|
|
Petr Vokac |
238799e |
+ perf_data->count = atoi(p + 19);
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
else if (strncasecmp("RemoteConnections:", p, 18) == 0)
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
- strcpy(perf_data->rconn, p + 19);
|
|
Petr Vokac |
238799e |
+ char *c = p+18;
|
|
Petr Vokac |
238799e |
+ while (isspace(*c)) c++;
|
|
Petr Vokac |
238799e |
+ snprintf(perf_data->rconn, sizeof(perf_data->rconn), "%s", c);
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
// skip unused dCache perf markers
|
|
Petr Vokac |
238799e |
else if (strncasecmp("State:", p, 6) == 0) {}
|
|
Petr Vokac |
238799e |
@@ -137,8 +140,12 @@ static size_t htext_copy_write_callback(char *buffer, size_t size, size_t nmemb,
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
handle->partial_done[perf_data->index] = perf_data->transferred;
|
|
Petr Vokac |
238799e |
handle->partial_total[perf_data->index] = 0;
|
|
Petr Vokac |
238799e |
- handle->partial_rconn[perf_data->index] = perf_data->rconn[0] != '\0' ? strdup(perf_data->rconn) : NULL;
|
|
Petr Vokac |
238799e |
-
|
|
Petr Vokac |
238799e |
+ if (perf_data->rconn[0] != '\0') {
|
|
Petr Vokac |
238799e |
+ if (!handle->partial_rconn[perf_data->index])
|
|
Petr Vokac |
238799e |
+ handle->partial_rconn[perf_data->index] = calloc(sizeof(char), HTEXT_PERF_MARKER_MAX_RCONN_SIZE);
|
|
Petr Vokac |
238799e |
+ if (strcmp(handle->partial_rconn[perf_data->index], perf_data->rconn))
|
|
Petr Vokac |
238799e |
+ strcpy(handle->partial_rconn[perf_data->index], perf_data->rconn);
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
@@ -257,8 +264,15 @@ void *htext_copy_method(void *h)
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
handle->http_status = control.http_status;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
+ /* Call transfer done callback */
|
|
Petr Vokac |
238799e |
+ if (GETPTR(handle, HTEXTOP_COPY_DONE)) {
|
|
Petr Vokac |
238799e |
+ void (*copy_done)(htext_handle *, int, void *) = GETPTR(handle, HTEXTOP_COPY_DONE);
|
|
Petr Vokac |
238799e |
+ copy_done(handle, handle->status, GETPTR(handle, HTEXTOP_COPY_DONE_DATA));
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
/* Clean up */
|
|
Petr Vokac |
238799e |
htext_partial_clean(&control);
|
|
Petr Vokac |
238799e |
curl_easy_cleanup(curl);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
return NULL ;
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/client/htext_get.c b/src/plugins/apache-httpd/src/client/htext_get.c
|
|
Petr Vokac |
238799e |
index 0fb49bde..ae9b686b 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/client/htext_get.c
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/client/htext_get.c
|
|
Petr Vokac |
238799e |
@@ -276,6 +276,13 @@ void *htext_get_method(void *h)
|
|
Petr Vokac |
238799e |
handle->status = HTEXTS_SUCCEEDED;
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
+ /* Call transfer done callback */
|
|
Petr Vokac |
238799e |
+ if (GETPTR(handle, HTEXTOP_COPY_DONE)) {
|
|
Petr Vokac |
238799e |
+ void (*copy_done)(htext_handle *, int, void *) = GETPTR(handle, HTEXTOP_COPY_DONE);
|
|
Petr Vokac |
238799e |
+ copy_done(handle, handle->status, GETPTR(handle, HTEXTOP_COPY_DONE_DATA));
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ /* Clean up */
|
|
Petr Vokac |
238799e |
curl_easy_cleanup(curl);
|
|
Petr Vokac |
238799e |
free(partial_array);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/client/htext_private.h b/src/plugins/apache-httpd/src/client/htext_private.h
|
|
Petr Vokac |
238799e |
index 0a406df7..b4369c1e 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/client/htext_private.h
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/client/htext_private.h
|
|
Petr Vokac |
238799e |
@@ -113,13 +113,14 @@ typedef struct htext_chunk htext_chunk;
|
|
Petr Vokac |
238799e |
* and unprocessed last line from input data
|
|
Petr Vokac |
238799e |
*/
|
|
Petr Vokac |
238799e |
#define HTEXT_PERF_MARKER_MAX_LINE_SIZE 1024
|
|
Petr Vokac |
238799e |
+#define HTEXT_PERF_MARKER_MAX_RCONN_SIZE 256
|
|
Petr Vokac |
238799e |
struct htext_perf_marker_parsed_data
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
time_t latest; /* Timestamp for received data */
|
|
Petr Vokac |
238799e |
int index; /* Stripe index */
|
|
Petr Vokac |
238799e |
off_t transferred; /* Stripe bytes transferred */
|
|
Petr Vokac |
238799e |
int count; /* Total stripe count */
|
|
Petr Vokac |
238799e |
- char rconn[HTEXT_PERF_MARKER_MAX_LINE_SIZE]; /* Remote connections */
|
|
Petr Vokac |
238799e |
+ char rconn[HTEXT_PERF_MARKER_MAX_RCONN_SIZE]; /* Remote connections */
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
char remaining[HTEXT_PERF_MARKER_MAX_LINE_SIZE]; /* Remaining input data from unterminated last line */
|
|
Petr Vokac |
238799e |
};
|
|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/client/htext_put.c b/src/plugins/apache-httpd/src/client/htext_put.c
|
|
Petr Vokac |
238799e |
index 0c3e4c1d..94d8781a 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/client/htext_put.c
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/client/htext_put.c
|
|
Petr Vokac |
238799e |
@@ -377,6 +377,12 @@ void *htext_put_method(void *h)
|
|
Petr Vokac |
238799e |
handle->status = HTEXTS_SUCCEEDED;
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
+ /* Call transfer done callback */
|
|
Petr Vokac |
238799e |
+ if (GETPTR(handle, HTEXTOP_COPY_DONE)) {
|
|
Petr Vokac |
238799e |
+ void (*copy_done)(htext_handle *, int, void *) = GETPTR(handle, HTEXTOP_COPY_DONE);
|
|
Petr Vokac |
238799e |
+ copy_done(handle, handle->status, GETPTR(handle, HTEXTOP_COPY_DONE_DATA));
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
curl_easy_cleanup(curl);
|
|
Petr Vokac |
238799e |
free(partial_array);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
diff --git a/src/plugins/apache-httpd/src/mod_lcgdm_disk/copy.c b/src/plugins/apache-httpd/src/mod_lcgdm_disk/copy.c
|
|
Petr Vokac |
238799e |
index dd586da6..cdc22c30 100644
|
|
Petr Vokac |
238799e |
--- a/src/plugins/apache-httpd/src/mod_lcgdm_disk/copy.c
|
|
Petr Vokac |
238799e |
+++ b/src/plugins/apache-httpd/src/mod_lcgdm_disk/copy.c
|
|
Petr Vokac |
238799e |
@@ -42,6 +42,8 @@ typedef struct
|
|
Petr Vokac |
238799e |
request_rec *request;
|
|
Petr Vokac |
238799e |
const char *source;
|
|
Petr Vokac |
238799e |
const char *destination;
|
|
Petr Vokac |
238799e |
+ pthread_mutex_t *done_lock;
|
|
Petr Vokac |
238799e |
+ pthread_cond_t *done_cond;
|
|
Petr Vokac |
238799e |
} dav_disk_copy_data;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
/* Custom I/O handler */
|
|
Petr Vokac |
238799e |
@@ -191,6 +193,30 @@ static void dav_disk_copy_log(htext_handle *handle, HTEXT_LOG_TYPE type,
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
+/**
|
|
Petr Vokac |
238799e |
+ * Called by htext when transfer is done
|
|
Petr Vokac |
238799e |
+ * @param handle The handle that triggers the call
|
|
Petr Vokac |
238799e |
+ * @param status The size of the message (it might not be NULL terminated)
|
|
Petr Vokac |
238799e |
+ * @param ud User defined data
|
|
Petr Vokac |
238799e |
+ */
|
|
Petr Vokac |
238799e |
+static void dav_disk_copy_done(htext_handle *handle, int status, void *ud)
|
|
Petr Vokac |
238799e |
+{
|
|
Petr Vokac |
238799e |
+ dav_disk_copy_data *ddc = (dav_disk_copy_data*) ud;
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ddc->request,
|
|
Petr Vokac |
238799e |
+ "Remote copy done (%d): %s => %s status %i",
|
|
Petr Vokac |
238799e |
+ htext_http_code(handle), ddc->source, ddc->destination, status);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ // send signal to finish perf marker loop
|
|
Petr Vokac |
238799e |
+ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ddc->request, "EEEE Remote copy done (%d): %s => %s status %i", htext_http_code(handle), ddc->source, ddc->destination, status);
|
|
Petr Vokac |
238799e |
+ pthread_mutex_lock(ddc->done_lock);
|
|
Petr Vokac |
238799e |
+ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ddc->request, "EEEE Remote copy done (%d): %s => %s status %i", htext_http_code(handle), ddc->source, ddc->destination, status);
|
|
Petr Vokac |
238799e |
+ pthread_cond_signal(ddc->done_cond);
|
|
Petr Vokac |
238799e |
+ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ddc->request, "EEEE Remote copy done (%d): %s => %s status %i", htext_http_code(handle), ddc->source, ddc->destination, status);
|
|
Petr Vokac |
238799e |
+ pthread_mutex_unlock(ddc->done_lock);
|
|
Petr Vokac |
238799e |
+ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ddc->request, "EEEE Remote copy done (%d): %s => %s status %i", htext_http_code(handle), ddc->source, ddc->destination, status);
|
|
Petr Vokac |
238799e |
+}
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
/**
|
|
Petr Vokac |
238799e |
* Generates and sends the performance clients following GridFTP format
|
|
Petr Vokac |
238799e |
* http://www.ogf.org/documents/GFD.20.pdf (Appendix II), skipping the
|
|
Petr Vokac |
238799e |
@@ -201,14 +223,14 @@ static void dav_disk_send_performance_markers(dav_disk_copy_data *ddc, size_t n,
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
(void) total;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
- char buf[80];
|
|
Petr Vokac |
238799e |
+ char buf[256+2]; // HTEXT_PERF_MARKER_MAX_RCONN_SIZE+2
|
|
Petr Vokac |
238799e |
time_t timestamp = time(NULL );
|
|
Petr Vokac |
238799e |
size_t i;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
for (i = 0; i < n; ++i) {
|
|
Petr Vokac |
238799e |
buf[0] = '\0';
|
|
Petr Vokac |
238799e |
if (rconn && rconn[i]) {
|
|
Petr Vokac |
238799e |
- snprintf(buf, 78, "\tRemoteConnections: %s", rconn[i]);
|
|
Petr Vokac |
238799e |
+ snprintf(buf, sizeof(buf)-2, "\tRemoteConnections: %s", rconn[i]);
|
|
Petr Vokac |
238799e |
strcat(buf, "\n"); // we reserved space for endl
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
apr_brigade_printf(ddc->brigade, ap_filter_flush, ddc->output,
|
|
Petr Vokac |
238799e |
@@ -228,52 +250,81 @@ static void dav_disk_send_performance_markers(dav_disk_copy_data *ddc, size_t n,
|
|
Petr Vokac |
238799e |
static dav_error *dav_disk_pool_and_feedback(htext_handle *handle,
|
|
Petr Vokac |
238799e |
dav_disk_copy_data *ddc)
|
|
Petr Vokac |
238799e |
{
|
|
Petr Vokac |
238799e |
- int wait, status;
|
|
Petr Vokac |
238799e |
+ int status, interval = 1, done = 0;
|
|
Petr Vokac |
238799e |
dav_error *error = NULL;
|
|
Petr Vokac |
238799e |
const char *error_string;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
- do {
|
|
Petr Vokac |
238799e |
- size_t *total, *done, n, i;
|
|
Petr Vokac |
238799e |
- size_t globalDone, globalTotal;
|
|
Petr Vokac |
238799e |
- char **rconn;
|
|
Petr Vokac |
238799e |
+ pthread_mutex_lock(ddc->done_lock);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
+ do {
|
|
Petr Vokac |
238799e |
status = htext_status(handle);
|
|
Petr Vokac |
238799e |
- switch (status) {
|
|
Petr Vokac |
238799e |
- case HTEXTS_SUCCEEDED:
|
|
Petr Vokac |
238799e |
- case HTEXTS_FAILED:
|
|
Petr Vokac |
238799e |
- case HTEXTS_ABORTED:
|
|
Petr Vokac |
238799e |
- wait = 0;
|
|
Petr Vokac |
238799e |
- break;
|
|
Petr Vokac |
238799e |
- default:
|
|
Petr Vokac |
238799e |
- /* In the first go we need to set the reply */
|
|
Petr Vokac |
238799e |
- if (ddc->request->status == 0) {
|
|
Petr Vokac |
238799e |
- ddc->request->status = HTTP_ACCEPTED;
|
|
Petr Vokac |
238799e |
- ap_set_content_type(ddc->request, "text/plain");
|
|
Petr Vokac |
238799e |
- }
|
|
Petr Vokac |
238799e |
- /* Print progress */
|
|
Petr Vokac |
238799e |
- htext_progress(handle, &n, &total, &done, &rconn);
|
|
Petr Vokac |
238799e |
- globalDone = globalTotal = 0;
|
|
Petr Vokac |
238799e |
- for (i = 0; i < n; ++i) {
|
|
Petr Vokac |
238799e |
- globalDone += done[i];
|
|
Petr Vokac |
238799e |
- globalTotal += total[i];
|
|
Petr Vokac |
238799e |
- }
|
|
Petr Vokac |
238799e |
-
|
|
Petr Vokac |
238799e |
- dav_disk_send_performance_markers(ddc, n, total, done, rconn);
|
|
Petr Vokac |
238799e |
-
|
|
Petr Vokac |
238799e |
- if (ap_fflush(ddc->output, ddc->brigade) == APR_SUCCESS) {
|
|
Petr Vokac |
238799e |
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ddc->request,
|
|
Petr Vokac |
238799e |
- "COPY '%s' %lu/%lu", ddc->request->uri,
|
|
Petr Vokac |
238799e |
- (unsigned long) globalDone,
|
|
Petr Vokac |
238799e |
- (unsigned long) globalTotal);
|
|
Petr Vokac |
238799e |
- wait = 1;
|
|
Petr Vokac |
238799e |
- sleep(1);
|
|
Petr Vokac |
238799e |
- }
|
|
Petr Vokac |
238799e |
- else {
|
|
Petr Vokac |
238799e |
- wait = 0;
|
|
Petr Vokac |
238799e |
- htext_abort(handle);
|
|
Petr Vokac |
238799e |
- }
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ if (status == HTEXTS_SUCCEEDED || status == HTEXTS_FAILED || status == HTEXTS_ABORTED) {
|
|
Petr Vokac |
238799e |
+ done = 1;
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ else {
|
|
Petr Vokac |
238799e |
+ struct timespec ts;
|
|
Petr Vokac |
238799e |
+ clock_gettime(CLOCK_REALTIME, &ts);
|
|
Petr Vokac |
238799e |
+ ts.tv_sec += interval;
|
|
Petr Vokac |
238799e |
+ interval = 5; // 5s between perf markers except for first one
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ int rc = pthread_cond_timedwait(ddc->done_cond, ddc->done_lock, &ts);
|
|
Petr Vokac |
238799e |
+ if (rc == 0) {
|
|
Petr Vokac |
238799e |
+ // transfer done, continue to get new status
|
|
Petr Vokac |
238799e |
+ continue;
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ else if (rc == ETIMEDOUT) {
|
|
Petr Vokac |
238799e |
+ // ongoing transfer, reached time to print new perfmarker
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ else {
|
|
Petr Vokac |
238799e |
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ddc->request,
|
|
Petr Vokac |
238799e |
+ "Waiting for perf marker condition failed for COPY '%s' rc %i",
|
|
Petr Vokac |
238799e |
+ ddc->request->uri, rc);
|
|
Petr Vokac |
238799e |
+ htext_abort(handle);
|
|
Petr Vokac |
238799e |
+ continue;
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ /* Always write last performance marker and in defined intervals */
|
|
Petr Vokac |
238799e |
+ {
|
|
Petr Vokac |
238799e |
+ size_t *total, *done, n, i;
|
|
Petr Vokac |
238799e |
+ size_t globalDone, globalTotal;
|
|
Petr Vokac |
238799e |
+ char **rconn;
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ /* In the first go we need to set the reply */
|
|
Petr Vokac |
238799e |
+ if (ddc->request->status == 0) {
|
|
Petr Vokac |
238799e |
+ ddc->request->status = HTTP_ACCEPTED;
|
|
Petr Vokac |
238799e |
+ ap_set_content_type(ddc->request, "text/plain");
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ /* Print progress */
|
|
Petr Vokac |
238799e |
+ htext_progress(handle, &n, &total, &done, &rconn);
|
|
Petr Vokac |
238799e |
+ dav_disk_send_performance_markers(ddc, n, total, done, rconn);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ globalDone = globalTotal = 0;
|
|
Petr Vokac |
238799e |
+ for (i = 0; i < n; ++i) {
|
|
Petr Vokac |
238799e |
+ globalDone += done[i];
|
|
Petr Vokac |
238799e |
+ globalTotal += total[i];
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ if (ap_fflush(ddc->output, ddc->brigade) == APR_SUCCESS) {
|
|
Petr Vokac |
238799e |
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ddc->request,
|
|
Petr Vokac |
238799e |
+ "COPY '%s' %lu/%lu", ddc->request->uri,
|
|
Petr Vokac |
238799e |
+ (unsigned long) globalDone,
|
|
Petr Vokac |
238799e |
+ (unsigned long) globalTotal);
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
+ else {
|
|
Petr Vokac |
238799e |
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ddc->request,
|
|
Petr Vokac |
238799e |
+ "Failed to send perf marker for COPY '%s' %lu/%lu",
|
|
Petr Vokac |
238799e |
+ ddc->request->uri,
|
|
Petr Vokac |
238799e |
+ (unsigned long) globalDone,
|
|
Petr Vokac |
238799e |
+ (unsigned long) globalTotal);
|
|
Petr Vokac |
238799e |
+ htext_abort(handle);
|
|
Petr Vokac |
238799e |
+ }
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
- } while (wait);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ } while (!done);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ pthread_mutex_unlock(ddc->done_lock);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
error_string = htext_error_string(handle);
|
|
Petr Vokac |
238799e |
switch (status) {
|
|
Petr Vokac |
238799e |
@@ -439,6 +490,8 @@ static dav_error *dav_disk_generic_copy(const dav_resource* res, const char* upr
|
|
Petr Vokac |
238799e |
dav_disk_copy_data ddc;
|
|
Petr Vokac |
238799e |
request_rec* req = res->info->request;
|
|
Petr Vokac |
238799e |
dav_disk_dir_conf* d_conf = res->info->d_conf;
|
|
Petr Vokac |
238799e |
+ pthread_mutex_t done_lock;
|
|
Petr Vokac |
238799e |
+ pthread_cond_t done_cond;
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
int oldcancel;
|
|
Petr Vokac |
238799e |
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldcancel);
|
|
Petr Vokac |
238799e |
@@ -475,6 +528,9 @@ static dav_error *dav_disk_generic_copy(const dav_resource* res, const char* upr
|
|
Petr Vokac |
238799e |
htext_setopt(handle, HTEXTOP_LOW_SPEED_TIME, d_conf->low_speed_time);
|
|
Petr Vokac |
238799e |
htext_setopt(handle, HTEXTOP_LOW_SPEED_LIMIT, d_conf->low_speed_limit);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
+ htext_setopt(handle, HTEXTOP_COPY_DONE, dav_disk_copy_done);
|
|
Petr Vokac |
238799e |
+ htext_setopt(handle, HTEXTOP_COPY_DONE_DATA, &ddc;;
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
htext_setopt(handle, HTEXTOP_LOGCALLBACK, dav_disk_copy_log);
|
|
Petr Vokac |
238799e |
htext_setopt(handle, HTEXTOP_LOGCALLBACK_DATA, &ddc;;
|
|
Petr Vokac |
238799e |
htext_setopt(handle, HTEXTOP_VERBOSITY, 2);
|
|
Petr Vokac |
238799e |
@@ -486,13 +542,23 @@ static dav_error *dav_disk_generic_copy(const dav_resource* res, const char* upr
|
|
Petr Vokac |
238799e |
ddc.request = req;
|
|
Petr Vokac |
238799e |
ddc.source = src;
|
|
Petr Vokac |
238799e |
ddc.destination = dst;
|
|
Petr Vokac |
238799e |
+ ddc.done_lock = &done_lock;
|
|
Petr Vokac |
238799e |
+ ddc.done_cond = &done_cond;
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ pthread_mutex_init(&done_lock, NULL);
|
|
Petr Vokac |
238799e |
+ pthread_cond_init(&done_cond, NULL);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
/* Run */
|
|
Petr Vokac |
238799e |
if (htext_perform(handle) != 0) {
|
|
Petr Vokac |
238799e |
error = dav_shared_new_error(req, NULL,
|
|
Petr Vokac |
238799e |
HTTP_INTERNAL_SERVER_ERROR, "Could not perform the action: %s",
|
|
Petr Vokac |
238799e |
htext_error_string(handle));
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ pthread_cond_destroy(&done_cond);
|
|
Petr Vokac |
238799e |
+ pthread_mutex_destroy(&done_lock);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
htext_destroy(handle);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
return error;
|
|
Petr Vokac |
238799e |
}
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
@@ -504,6 +570,9 @@ static dav_error *dav_disk_generic_copy(const dav_resource* res, const char* upr
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
/* Finish */
|
|
Petr Vokac |
238799e |
htext_destroy(handle);
|
|
Petr Vokac |
238799e |
+
|
|
Petr Vokac |
238799e |
+ pthread_cond_destroy(&done_cond);
|
|
Petr Vokac |
238799e |
+ pthread_mutex_destroy(&done_lock);
|
|
Petr Vokac |
238799e |
|
|
Petr Vokac |
238799e |
if (!error) {
|
|
Petr Vokac |
238799e |
bkt = apr_bucket_eos_create(ddc.output->c->bucket_alloc);
|