All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nick Hengeveld <nickh@reactrix.com>
To: git@vger.kernel.org
Subject: [PATCH 4/4] Refresh the remote lock if it is about to expire
Date: Fri, 4 Nov 2005 14:22:35 -0800	[thread overview]
Message-ID: <20051104222235.GG3001@reactrix.com> (raw)

Refresh the remote lock if it is about to expire

Signed-off-by: Nick Hengeveld <nickh@reactrix.com>


---

 http-push.c |  106 ++++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 79 insertions(+), 27 deletions(-)

applies-to: 678d5afb150b94bf4a516f852cd41f6920e8642b
197abe5895bea9924c8f01398d9fc73ec013cbd5
diff --git a/http-push.c b/http-push.c
index 85cd595..c10067c 100644
--- a/http-push.c
+++ b/http-push.c
@@ -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;
@@ -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
@@ -580,11 +585,65 @@ static void start_move(struct transfer_r
 	}
 }
 
+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) {
@@ -1114,7 +1173,7 @@ end_lockprop_element(void *userData, con
 	}
 }
 
-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;
@@ -1175,8 +1234,9 @@ struct active_lock *lock_remote(char *fi
 	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");
 
@@ -1211,7 +1271,6 @@ struct active_lock *lock_remote(char *fi
 		return NULL;
 	}
 
-	free(url);
 	free(out_data);
 
 	XML_SetUserData(parser, new_lock);
@@ -1223,6 +1282,7 @@ struct active_lock *lock_remote(char *fi
 	if (result != XML_STATUS_OK) {
 		fprintf(stderr, "%s", XML_ErrorString(
 				XML_GetErrorCode(parser)));
+		free(url);
 		free(new_lock);
 		return NULL;
 	}
@@ -1232,18 +1292,19 @@ struct active_lock *lock_remote(char *fi
 			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;
@@ -1251,13 +1312,11 @@ int unlock_remote(char *file, struct act
 	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);
 
@@ -1274,7 +1333,12 @@ int unlock_remote(char *file, struct act
 
 	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;
 }
@@ -1423,20 +1487,15 @@ void get_delta(unsigned char *sha1, stru
 	}
 }
 
-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);
@@ -1460,13 +1519,12 @@ int update_remote(char *remote_path, uns
 	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",
@@ -1477,7 +1535,6 @@ int update_remote(char *remote_path, uns
 	} else {
 		free(out_data);
 		free(if_header);
-		free(url);
 		fprintf(stderr, "Unable to start PUT request\n");
 		return 0;
 	}
@@ -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);
@@ -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",
@@ -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:
---
0.99.9.GIT

                 reply	other threads:[~2005-11-04 22:22 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20051104222235.GG3001@reactrix.com \
    --to=nickh@reactrix.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.