{"thread":{"id":"2355","subject":"[PATCH 4/4] Refresh the remote lock if it is about to expire","startedAt":"2005-11-04T22:22:35Z","lastAt":"2005-11-04T22:22:35Z","messageCount":1,"participants":["Nick Hengeveld"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"11162","messageId":"20051104222235.GG3001@reactrix.com","threadId":"2355","inReplyTo":null,"subject":"[PATCH 4/4] Refresh the remote lock if it is about to expire","fromName":"Nick Hengeveld","fromEmail":"nickh@reactrix.com","sentAt":"2005-11-04T22:22:35Z","receivedAt":"2005-11-04T22:22:35Z","isPatch":true,"sender":{"key":"nickh@reactrix.com","avatar":null},"body":"Refresh the remote lock if it is about to expire\n\nSigned-off-by: Nick Hengeveld <nickh@reactrix.com>\n\n\n---\n\n http-push.c |  106 ++++++++++++++++++++++++++++++++++++++++++++---------------\n 1 files changed, 79 insertions(+), 27 deletions(-)\n\napplies-to: 678d5afb150b94bf4a516f852cd41f6920e8642b\n197abe5895bea9924c8f01398d9fc73ec013cbd5\ndiff --git a/http-push.c b/http-push.c\nindex 85cd595..c10067c 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -40,6 +40,9 @@ static const char http_push_usage[] =\n #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>\"\n #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>\"\n \n+#define LOCK_TIME 600\n+#define LOCK_REFRESH 30\n+\n static int active_requests = 0;\n static int data_received;\n static int pushing = 0;\n@@ -143,10 +146,12 @@ struct active_lock\n \tint ctx_timeout;\n \tint ctx_locktoken;\n \tint ctx_locktoken_href;\n+\tchar *url;\n \tchar *owner;\n+\tchar *token;\n \ttime_t start_time;\n \tlong timeout;\n-\tchar *token;\n+\tint refreshing;\n };\n \n struct lockprop\n@@ -580,11 +585,65 @@ static void start_move(struct transfer_r\n \t}\n }\n \n+int refresh_lock(struct active_lock *lock)\n+{\n+\tstruct active_request_slot *slot;\n+\tchar *if_header;\n+\tchar timeout_header[25];\n+\tstruct curl_slist *dav_headers = NULL;\n+\tint rc = 0;\n+\n+\tlock->refreshing = 1;\n+\n+\tif_header = xmalloc(strlen(lock->token) + 25);\n+\tsprintf(if_header, \"If: (<opaquelocktoken:%s>)\", lock->token);\n+\tsprintf(timeout_header, \"Timeout: Second-%ld\", lock->timeout);\n+\tdav_headers = curl_slist_append(dav_headers, if_header);\n+\tdav_headers = curl_slist_append(dav_headers, timeout_header);\n+\n+\tslot = get_active_slot();\n+\tcurl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_LOCK);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);\n+\n+\tif (start_active_slot(slot)) {\n+\t\trun_active_slot(slot);\n+\t\tif (slot->curl_result != CURLE_OK) {\n+\t\t\tfprintf(stderr, \"Got HTTP error %ld\\n\", slot->http_code);\n+\t\t} else {\n+\t\t\tlock->start_time = time(NULL);\n+\t\t\trc = 1;\n+\t\t}\n+\t}\n+\n+\tlock->refreshing = 0;\n+\tcurl_slist_free_all(dav_headers);\n+\tfree(if_header);\n+\n+\treturn rc;\n+}\n+\n static void finish_request(struct transfer_request *request)\n {\n+\ttime_t current_time = time(NULL);\n+\tint time_remaining;\n+\n \trequest->curl_result =\trequest->slot->curl_result;\n \trequest->http_code = request->slot->http_code;\n \trequest->slot = NULL;\n+\n+\t/* Refresh the lock if it is close to timing out */\n+\ttime_remaining = request->lock->start_time + request->lock->timeout\n+\t\t- current_time;\n+\tif (time_remaining < LOCK_REFRESH && !request->lock->refreshing) {\n+\t\tif (!refresh_lock(request->lock)) {\n+\t\t\tfprintf(stderr, \"Unable to refresh remote lock\\n\");\n+\t\t\taborted = 1;\n+\t\t}\n+\t}\n+\n \tif (request->headers != NULL)\n \t\tcurl_slist_free_all(request->headers);\n \tif (request->state == RUN_HEAD) {\n@@ -1114,7 +1173,7 @@ end_lockprop_element(void *userData, con\n \t}\n }\n \n-struct active_lock *lock_remote(char *file, int timeout)\n+struct active_lock *lock_remote(char *file, long timeout)\n {\n \tstruct active_request_slot *slot;\n \tstruct buffer out_buffer;\n@@ -1175,8 +1234,9 @@ struct active_lock *lock_remote(char *fi\n \tnew_lock->owner = NULL;\n \tnew_lock->token = NULL;\n \tnew_lock->timeout = -1;\n+\tnew_lock->refreshing = 0;\n \n-\tsprintf(timeout_header, \"Timeout: Second-%d\", timeout);\n+\tsprintf(timeout_header, \"Timeout: Second-%ld\", timeout);\n \tdav_headers = curl_slist_append(dav_headers, timeout_header);\n \tdav_headers = curl_slist_append(dav_headers, \"Content-Type: text/xml\");\n \n@@ -1211,7 +1271,6 @@ struct active_lock *lock_remote(char *fi\n \t\treturn NULL;\n \t}\n \n-\tfree(url);\n \tfree(out_data);\n \n \tXML_SetUserData(parser, new_lock);\n@@ -1223,6 +1282,7 @@ struct active_lock *lock_remote(char *fi\n \tif (result != XML_STATUS_OK) {\n \t\tfprintf(stderr, \"%s\", XML_ErrorString(\n \t\t\t\tXML_GetErrorCode(parser)));\n+\t\tfree(url);\n \t\tfree(new_lock);\n \t\treturn NULL;\n \t}\n@@ -1232,18 +1292,19 @@ struct active_lock *lock_remote(char *fi\n \t\t\tfree(new_lock->token);\n \t\tif (new_lock->owner != NULL)\n \t\t\tfree(new_lock->owner);\n+\t\tfree(url);\n \t\tfree(new_lock);\n \t\treturn NULL;\n \t}\n \n+\tnew_lock->url = url;\n \tnew_lock->start_time = time(NULL);\n \treturn new_lock;\n }\n \n-int unlock_remote(char *file, struct active_lock *lock)\n+int unlock_remote(struct active_lock *lock)\n {\n \tstruct active_request_slot *slot;\n-\tchar *url;\n \tchar *lock_token_header;\n \tstruct curl_slist *dav_headers = NULL;\n \tint rc = 0;\n@@ -1251,13 +1312,11 @@ int unlock_remote(char *file, struct act\n \tlock_token_header = xmalloc(strlen(lock->token) + 31);\n \tsprintf(lock_token_header, \"Lock-Token: <opaquelocktoken:%s>\",\n \t\tlock->token);\n-\turl = xmalloc(strlen(remote->url) + strlen(file) + 1);\n-\tsprintf(url, \"%s%s\", remote->url, file);\n \tdav_headers = curl_slist_append(dav_headers, lock_token_header);\n \n \tslot = get_active_slot();\n \tcurl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_null);\n-\tcurl_easy_setopt(slot->curl, CURLOPT_URL, url);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);\n \tcurl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, DAV_UNLOCK);\n \tcurl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);\n \n@@ -1274,7 +1333,12 @@ int unlock_remote(char *file, struct act\n \n \tcurl_slist_free_all(dav_headers);\n \tfree(lock_token_header);\n-\tfree(url);\n+\n+\tif (lock->owner != NULL)\n+\t\tfree(lock->owner);\n+\tfree(lock->url);\n+\tfree(lock->token);\n+\tfree(lock);\n \n \treturn rc;\n }\n@@ -1423,20 +1487,15 @@ void get_delta(unsigned char *sha1, stru\n \t}\n }\n \n-int update_remote(char *remote_path, unsigned char *sha1,\n-\t\t  struct active_lock *lock)\n+int update_remote(unsigned char *sha1, struct active_lock *lock)\n {\n \tstruct active_request_slot *slot;\n-\tchar *url;\n \tchar *out_data;\n \tchar *if_header;\n \tstruct buffer out_buffer;\n \tstruct curl_slist *dav_headers = NULL;\n \tint i;\n \n-\turl = xmalloc(strlen(remote->url) + strlen(remote_path) + 1);\n-\tsprintf(url, \"%s%s\", remote->url, remote_path);\n-\n \tif_header = xmalloc(strlen(lock->token) + 25);\n \tsprintf(if_header, \"If: (<opaquelocktoken:%s>)\", lock->token);\n \tdav_headers = curl_slist_append(dav_headers, if_header);\n@@ -1460,13 +1519,12 @@ int update_remote(char *remote_path, uns\n \tcurl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, dav_headers);\n \tcurl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 1);\n \tcurl_easy_setopt(slot->curl, CURLOPT_PUT, 1);\n-\tcurl_easy_setopt(slot->curl, CURLOPT_URL, url);\n+\tcurl_easy_setopt(slot->curl, CURLOPT_URL, lock->url);\n \n \tif (start_active_slot(slot)) {\n \t\trun_active_slot(slot);\n \t\tfree(out_data);\n \t\tfree(if_header);\n-\t\tfree(url);\n \t\tif (slot->curl_result != CURLE_OK) {\n \t\t\tfprintf(stderr,\n \t\t\t\t\"PUT error: curl result=%d, HTTP code=%ld\\n\",\n@@ -1477,7 +1535,6 @@ int update_remote(char *remote_path, uns\n \t} else {\n \t\tfree(out_data);\n \t\tfree(if_header);\n-\t\tfree(url);\n \t\tfprintf(stderr, \"Unable to start PUT request\\n\");\n \t\treturn 0;\n \t}\n@@ -1629,7 +1686,7 @@ int main(int argc, char **argv)\n \t\t\tfree(remote_path);\n \t\tremote_path = xmalloc(strlen(remote_ref) + 12);\n \t\tsprintf(remote_path, \"refs/heads/%s\", remote_ref);\n-\t\tremote_lock = lock_remote(remote_path, 3600);\n+\t\tremote_lock = lock_remote(remote_path, LOCK_TIME);\n \t\tif (remote_lock == NULL) {\n \t\t\tfprintf(stderr, \"Unable to lock remote branch %s\\n\",\n \t\t\t\tremote_ref);\n@@ -1701,8 +1758,7 @@ int main(int argc, char **argv)\n \n \t\t/* Update the remote branch if all went well */\n \t\tif (do_remote_update) {\n-\t\t\tif (!aborted && update_remote(remote_path,\n-\t\t\t\t\t\t      local_sha1,\n+\t\t\tif (!aborted && update_remote(local_sha1,\n \t\t\t\t\t\t      remote_lock)) {\n \t\t\t\tfprintf(stderr, \"%s remote branch %s\\n\",\n \t\t\t\t\tnew_branch ? \"Created\" : \"Updated\",\n@@ -1718,12 +1774,8 @@ int main(int argc, char **argv)\n \t\t}\n \n \tunlock:\n-\t\tunlock_remote(remote_path, remote_lock);\n+\t\tunlock_remote(remote_lock);\n \t\tfree(remote_path);\n-\t\tif (remote_lock->owner != NULL)\n-\t\t\tfree(remote_lock->owner);\n-\t\tfree(remote_lock->token);\n-\t\tfree(remote_lock);\n \t}\n \n  cleanup:\n---\n0.99.9.GIT\n"}]}