Skip to content

Commit

Permalink
Refresh the remote lock if it is about to expire
Browse files Browse the repository at this point in the history
Refresh the remote lock if it is about to expire

Signed-off-by: Nick Hengeveld <nickh@reactrix.com>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Nick Hengeveld authored and Junio C Hamano committed Nov 6, 2005
1 parent 26349b2 commit 75187c9
Showing 1 changed file with 79 additions and 27 deletions.
106 changes: 79 additions & 27 deletions http-push.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ static const char http_push_usage[] =
#define PROPFIND_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"%s\">\n<D:supportedlock/>\n</D:prop>\n</D:propfind>"
#define LOCK_REQUEST "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:lockinfo xmlns:D=\"DAV:\">\n<D:lockscope><D:exclusive/></D:lockscope>\n<D:locktype><D:write/></D:locktype>\n<D:owner>\n<D:href>mailto:%s</D:href>\n</D:owner>\n</D:lockinfo>"

#define LOCK_TIME 600
#define LOCK_REFRESH 30

static int active_requests = 0;
static int data_received;
static int pushing = 0;
Expand Down Expand Up @@ -143,10 +146,12 @@ struct active_lock
int ctx_timeout;
int ctx_locktoken;
int ctx_locktoken_href;
char *url;
char *owner;
char *token;
time_t start_time;
long timeout;
char *token;
int refreshing;
};

struct lockprop
Expand Down Expand Up @@ -580,11 +585,65 @@ static void start_move(struct transfer_request *request)
}
}

int refresh_lock(struct active_lock *lock)
{
struct active_request_slot *slot;
char *if_header;
char timeout_header[25];
struct curl_slist *dav_headers = NULL;
int rc = 0;

lock->refreshing = 1;

if_header = xmalloc(strlen(lock->token) + 25);
sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
sprintf(timeout_header, "Timeout: Second-%ld", lock->timeout);
dav_headers = curl_slist_append(dav_headers, if_header);
dav_headers = curl_slist_append(dav_headers, timeout_header);

slot = get_active_slot();
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);

if (start_active_slot(slot)) {
run_active_slot(slot);
if (slot->curl_result != CURLE_OK) {
fprintf(stderr, "Got HTTP error %ld\n", slot->http_code);
} else {
lock->start_time = time(NULL);
rc = 1;
}
}

lock->refreshing = 0;
curl_slist_free_all(dav_headers);
free(if_header);

return rc;
}

static void finish_request(struct transfer_request *request)
{
time_t current_time = time(NULL);
int time_remaining;

request->curl_result = request->slot->curl_result;
request->http_code = request->slot->http_code;
request->slot = NULL;

/* Refresh the lock if it is close to timing out */
time_remaining = request->lock->start_time + request->lock->timeout
- current_time;
if (time_remaining < LOCK_REFRESH && !request->lock->refreshing) {
if (!refresh_lock(request->lock)) {
fprintf(stderr, "Unable to refresh remote lock\n");
aborted = 1;
}
}

if (request->headers != NULL)
curl_slist_free_all(request->headers);
if (request->state == RUN_HEAD) {
Expand Down Expand Up @@ -1114,7 +1173,7 @@ end_lockprop_element(void *userData, const char *name)
}
}

struct active_lock *lock_remote(char *file, int timeout)
struct active_lock *lock_remote(char *file, long timeout)
{
struct active_request_slot *slot;
struct buffer out_buffer;
Expand Down Expand Up @@ -1175,8 +1234,9 @@ struct active_lock *lock_remote(char *file, int timeout)
new_lock->owner = NULL;
new_lock->token = NULL;
new_lock->timeout = -1;
new_lock->refreshing = 0;

sprintf(timeout_header, "Timeout: Second-%d", timeout);
sprintf(timeout_header, "Timeout: Second-%ld", timeout);
dav_headers = curl_slist_append(dav_headers, timeout_header);
dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");

Expand Down Expand Up @@ -1211,7 +1271,6 @@ struct active_lock *lock_remote(char *file, int timeout)
return NULL;
}

free(url);
free(out_data);

XML_SetUserData(parser, new_lock);
Expand All @@ -1223,6 +1282,7 @@ struct active_lock *lock_remote(char *file, int timeout)
if (result != XML_STATUS_OK) {
fprintf(stderr, "%s", XML_ErrorString(
XML_GetErrorCode(parser)));
free(url);
free(new_lock);
return NULL;
}
Expand All @@ -1232,32 +1292,31 @@ struct active_lock *lock_remote(char *file, int timeout)
free(new_lock->token);
if (new_lock->owner != NULL)
free(new_lock->owner);
free(url);
free(new_lock);
return NULL;
}

new_lock->url = url;
new_lock->start_time = time(NULL);
return new_lock;
}

int unlock_remote(char *file, struct active_lock *lock)
int unlock_remote(struct active_lock *lock)
{
struct active_request_slot *slot;
char *url;
char *lock_token_header;
struct curl_slist *dav_headers = NULL;
int rc = 0;

lock_token_header = xmalloc(strlen(lock->token) + 31);
sprintf(lock_token_header, "Lock-Token: <opaquelocktoken:%s>",
lock->token);
url = xmalloc(strlen(remote->url) + strlen(file) + 1);
sprintf(url, "%s%s", remote->url, file);
dav_headers = curl_slist_append(dav_headers, lock_token_header);

slot = get_active_slot();
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);
curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);

Expand All @@ -1274,7 +1333,12 @@ int unlock_remote(char *file, struct active_lock *lock)

curl_slist_free_all(dav_headers);
free(lock_token_header);
free(url);

if (lock->owner != NULL)
free(lock->owner);
free(lock->url);
free(lock->token);
free(lock);

return rc;
}
Expand Down Expand Up @@ -1423,20 +1487,15 @@ void get_delta(unsigned char *sha1, struct object *obj,
}
}

int update_remote(char *remote_path, unsigned char *sha1,
struct active_lock *lock)
int update_remote(unsigned char *sha1, struct active_lock *lock)
{
struct active_request_slot *slot;
char *url;
char *out_data;
char *if_header;
struct buffer out_buffer;
struct curl_slist *dav_headers = NULL;
int i;

url = xmalloc(strlen(remote->url) + strlen(remote_path) + 1);
sprintf(url, "%s%s", remote->url, remote_path);

if_header = xmalloc(strlen(lock->token) + 25);
sprintf(if_header, "If: (<opaquelocktoken:%s>)", lock->token);
dav_headers = curl_slist_append(dav_headers, if_header);
Expand All @@ -1460,13 +1519,12 @@ int update_remote(char *remote_path, unsigned char *sha1,
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);
curl_easy_setopt(slot->curl, CURLOPT_PUT, 1);
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);

if (start_active_slot(slot)) {
run_active_slot(slot);
free(out_data);
free(if_header);
free(url);
if (slot->curl_result != CURLE_OK) {
fprintf(stderr,
"PUT error: curl result=%d, HTTP code=%ld\n",
Expand All @@ -1477,7 +1535,6 @@ int update_remote(char *remote_path, unsigned char *sha1,
} else {
free(out_data);
free(if_header);
free(url);
fprintf(stderr, "Unable to start PUT request\n");
return 0;
}
Expand Down Expand Up @@ -1629,7 +1686,7 @@ int main(int argc, char **argv)
free(remote_path);
remote_path = xmalloc(strlen(remote_ref) + 12);
sprintf(remote_path, "refs/heads/%s", remote_ref);
remote_lock = lock_remote(remote_path, 3600);
remote_lock = lock_remote(remote_path, LOCK_TIME);
if (remote_lock == NULL) {
fprintf(stderr, "Unable to lock remote branch %s\n",
remote_ref);
Expand Down Expand Up @@ -1701,8 +1758,7 @@ int main(int argc, char **argv)

/* Update the remote branch if all went well */
if (do_remote_update) {
if (!aborted && update_remote(remote_path,
local_sha1,
if (!aborted && update_remote(local_sha1,
remote_lock)) {
fprintf(stderr, "%s remote branch %s\n",
new_branch ? "Created" : "Updated",
Expand All @@ -1718,12 +1774,8 @@ int main(int argc, char **argv)
}

unlock:
unlock_remote(remote_path, remote_lock);
unlock_remote(remote_lock);
free(remote_path);
if (remote_lock->owner != NULL)
free(remote_lock->owner);
free(remote_lock->token);
free(remote_lock);
}

cleanup:
Expand Down

0 comments on commit 75187c9

Please sign in to comment.