Improve lock handling
PATCH 3/4 Improve lock handling
Improve lock handling: parse the server response for the timeout, owner, and lock token
Signed-off-by Nick Hengeveld <[email protected]>
---
http-push.c | 201 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 147 insertions(+), 54 deletions(-)
applies-to: 99366e40c96e3fd0436287c601697f3166e8cf36 1b26b4528dc9e14f2be5d57154022249206fcc6f
http-push.c +147 -54
@@ -55,7 +55,6 @@ static CURL *curl_default;static struct curl_slist *no_pragma_header;static struct curl_slist *default_headers;static char curl_errorstr[CURL_ERROR_SIZE ]; -static char *lock_token =NULL ;static int push_verbosely =0 ;static int push_all =0 ;
@@ -92,7 +91,7 @@ struct transfer_requestunsigned char sha1[20 ];char *url;char *dest; -char *lock_token; +struct active_lock *lock;struct curl_slist *headers;struct buffer buffer;char filename[PATH_MAX ];
@@ -136,6 +135,20 @@ static char *ssl_cainfo = NULL;static long curl_low_speed_limit =-1 ;static long curl_low_speed_time =-1 ; +struct active_lock +{ +int ctx_activelock; +int ctx_owner; +int ctx_owner_href; +int ctx_timeout; +int ctx_locktoken; +int ctx_locktoken_href; +char *owner; +time_t start_time; +long timeout; +char *token; +}; +struct lockprop {int supported_lock;
@@ -509,7 +522,7 @@ static void start_put(struct transfer_reif (request->url !=NULL )free (request->url); request->url =xmalloc (strlen (remote->url) + -strlen (request->lock_token) +51 ); +strlen (request->lock->token) +51 );strcpy (request->url, remote->url); posn = request->url +strlen (remote->url);strcpy (posn,"objects/" );
@@ -522,7 +535,7 @@ static void start_put(struct transfer_resprintf (request->dest,"Destination: %s" , request->url); posn +=38 ; *(posn++) ='.' ; -strcpy (posn, request->lock_token); +strcpy (posn, request->lock->token); slot =get_active_slot ();curl_easy_setopt (slot->curl,CURLOPT_INFILE , &request->buffer);
@@ -724,7 +737,7 @@ void process_waiting_requests(void) } } -void add_request (unsigned char *sha1,char *lock_token) +void add_request (unsigned char *sha1,struct active_lock *lock) {struct transfer_request *request = request_queue_head;struct packed_git *target;
@@ -741,7 +754,7 @@ void add_request(unsigned char *sha1, ch request =xmalloc (sizeof (*request));memcpy (request->sha1, sha1,20 ); request->url =NULL ; - request->lock_token = lock_token; + request->lock = lock; request->headers =NULL ; request->state =NEED_CHECK ; request->next = request_queue_head;
@@ -999,6 +1012,68 @@ int fetch_ref(char *ref, unsigned char * }static void +start_activelock_element (void *userData,const char *name,const char **atts) +{ +struct active_lock *lock = (struct active_lock *)userData; + +if (lock->ctx_activelock && !strcmp (name,"D:timeout" )) + lock->ctx_timeout =1 ; +else if (lock->ctx_owner &&strstr (name,"href" )) + lock->ctx_owner_href =1 ; +else if (lock->ctx_activelock &&strstr (name,"owner" )) + lock->ctx_owner =1 ; +else if (lock->ctx_locktoken && !strcmp (name,"D:href" )) + lock->ctx_locktoken_href =1 ; +else if (lock->ctx_activelock && !strcmp (name,"D:locktoken" )) + lock->ctx_locktoken =1 ; +else if (!strcmp (name,"D:activelock" )) + lock->ctx_activelock =1 ; +} + +static void +end_activelock_element (void *userData,const char *name) +{ +struct active_lock *lock = (struct active_lock *)userData; + +if (lock->ctx_timeout && !strcmp (name,"D:timeout" )) { + lock->ctx_timeout =0 ; + }else if (lock->ctx_owner_href &&strstr (name,"href" )) { + lock->ctx_owner_href =0 ; + }else if (lock->ctx_owner &&strstr (name,"owner" )) { + lock->ctx_owner =0 ; + }else if (lock->ctx_locktoken_href && !strcmp (name,"D:href" )) { + lock->ctx_locktoken_href =0 ; + }else if (lock->ctx_locktoken && !strcmp (name,"D:locktoken" )) { + lock->ctx_locktoken =0 ; + }else if (lock->ctx_activelock && !strcmp (name,"D:activelock" )) { + lock->ctx_activelock =0 ; + } +} + +static void +activelock_cdata (void *userData,const XML_Char *s,int len) +{ +struct active_lock *lock = (struct active_lock *)userData; +char *this =malloc (len+1 ); +strncpy (this, s, len); + +if (lock->ctx_owner_href) { + lock->owner =malloc (len+1 ); +strcpy (lock->owner, this); + }else if (lock->ctx_locktoken_href) { +if (!strncmp (this,"opaquelocktoken:" ,16 )) { + lock->token =malloc (len-15 ); +strcpy (lock->token, this+16 ); + } + }else if (lock->ctx_timeout) { +if (!strncmp (this,"Second-" ,7 )) + lock->timeout =strtol (this+7 ,NULL ,10 ); + } + +free (this); +} + +static void start_lockprop_element (void *userData,const char *name,const char **atts) {struct lockprop *prop = (struct lockprop *)userData;
@@ -1039,40 +1114,21 @@ end_lockprop_element(void *userData, con } } -size_t process_lock_header (void *ptr,size_t size,size_t nmemb,void *stream) -{ -size_t header_size = size*nmemb; -char *start; -char *end; - -if (!strncmp (ptr,"Lock-Token: <opaquelocktoken:" ,29 )) { - start = ptr +29 ; -for (end = ptr + header_size; - *(end -1 ) =='\r' || *(end -1 ) =='\n' || *(end -1 ) =='>' ; - end--) {} -if (end > start) { - lock_token =xmalloc (end - start +1 ); -memcpy (lock_token, start, end - start); - lock_token[end - start] =0 ; - } - } - -return header_size; -} - -char *lock_remote (char *file,int timeout) +struct active_lock *lock_remote (char *file,int timeout) {struct active_request_slot *slot;struct buffer out_buffer; +struct buffer in_buffer;char *out_data; +char *in_data;char *url;char *ep;char timeout_header[25 ]; +struct active_lock *new_lock; +XML_Parser parser =XML_ParserCreate (NULL ); +enum XML_Status result;struct curl_slist *dav_headers =NULL ; -if (lock_token !=NULL ) -free (lock_token); - url =xmalloc (strlen (remote->url) +strlen (file) +1 );sprintf (url,"%s%s" , remote->url, file);
@@ -1110,6 +1166,16 @@ char *lock_remote(char *file, int timeou out_buffer.posn =0 ; out_buffer.buffer = out_data; + in_buffer.size =4096 ; + in_data =xmalloc (in_buffer.size); + in_buffer.posn =0 ; + in_buffer.buffer = in_data; + + new_lock =xmalloc (sizeof (*new_lock)); + new_lock->owner =NULL ; + new_lock->token =NULL ; + new_lock->timeout =-1 ; +sprintf (timeout_header,"Timeout: Second-%d" , timeout); dav_headers =curl_slist_append (dav_headers, timeout_header); dav_headers =curl_slist_append (dav_headers,"Content-Type: text/xml" );
@@ -1118,9 +1184,9 @@ char *lock_remote(char *file, int timeoucurl_easy_setopt (slot->curl,CURLOPT_INFILE , &out_buffer);curl_easy_setopt (slot->curl,CURLOPT_INFILESIZE , out_buffer.size);curl_easy_setopt (slot->curl,CURLOPT_READFUNCTION , fread_buffer); -curl_easy_setopt (slot->curl,CURLOPT_WRITEFUNCTION , fwrite_null); -curl_easy_setopt (slot->curl,CURLOPT_HEADERFUNCTION , - process_lock_header); +curl_easy_setopt (slot->curl,CURLOPT_FILE , &in_buffer); +curl_easy_setopt (slot->curl,CURLOPT_WRITEFUNCTION , + fwrite_buffer_dynamic);curl_easy_setopt (slot->curl,CURLOPT_URL , url);curl_easy_setopt (slot->curl,CURLOPT_UPLOAD ,1 );curl_easy_setopt (slot->curl,CURLOPT_CUSTOMREQUEST ,DAV_LOCK );
@@ -1130,13 +1196,17 @@ char *lock_remote(char *file, int timeourun_active_slot (slot);if (slot->curl_result !=CURLE_OK ) {fprintf (stderr,"Got HTTP error %ld\n" , slot->http_code); +free (new_lock);free (url);free (out_data); +free (in_data);return NULL ; } }else { +free (new_lock);free (url);free (out_data); +free (in_data);fprintf (stderr,"Unable to start request\n" );return NULL ; }
@@ -1144,10 +1214,33 @@ char *lock_remote(char *file, int timeoufree (url);free (out_data); -return strdup (lock_token); +XML_SetUserData (parser, new_lock); +XML_SetElementHandler (parser, start_activelock_element, + end_activelock_element); +XML_SetCharacterDataHandler (parser, activelock_cdata); + result =XML_Parse (parser, in_buffer.buffer, in_buffer.posn,1 ); +free (in_data); +if (result !=XML_STATUS_OK ) { +fprintf (stderr,"%s" ,XML_ErrorString ( +XML_GetErrorCode (parser))); +free (new_lock); +return NULL ; + } + +if (new_lock->token ==NULL || new_lock->timeout <=0 ) { +if (new_lock->token !=NULL ) +free (new_lock->token); +if (new_lock->owner !=NULL ) +free (new_lock->owner); +free (new_lock); +return NULL ; + } + + new_lock->start_time =time (NULL ); +return new_lock; } -int unlock_remote (char *file,char *lock_token) +int unlock_remote (char *file,struct active_lock *lock) {struct active_request_slot *slot;char *url;
@@ -1155,14 +1248,9 @@ int unlock_remote(char *file, char *lockstruct curl_slist *dav_headers =NULL ;int rc =0 ; -if (lock_token ==NULL ) { -fprintf (stderr,"Unable to unlock, no lock token" ); -return 0 ; - } - - lock_token_header =xmalloc (strlen (lock_token) +31 ); + lock_token_header =xmalloc (strlen (lock->token) +31 );sprintf (lock_token_header,"Lock-Token: <opaquelocktoken:%s>" , - lock_token); + 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);
@@ -1278,7 +1366,8 @@ int is_ancestor(unsigned char *sha1, strreturn 0 ; } -void get_delta (unsigned char *sha1,struct object *obj,char *lock_token) +void get_delta (unsigned char *sha1,struct object *obj, +struct active_lock *lock) {struct commit *commit;struct commit_list *parents;
@@ -1294,7 +1383,7 @@ void get_delta(unsigned char *sha1, struif (obj->type == commit_type) {if (push_verbosely)fprintf (stderr,"walk %s\n" ,sha1_to_hex (obj->sha1)); -add_request (obj->sha1, lock_token); +add_request (obj->sha1, lock); commit = (struct commit *)obj;if (parse_commit (commit)) { fprintf(stderr, "Error parsing commit %s\n",
@@ -1307,12 +1396,12 @@ void get_delta(unsigned char *sha1, struif (sha1 ==NULL ||memcmp (sha1, parents->item->object.sha1,20 ))get_delta (sha1, &parents->item->object, - lock_token); -get_delta (sha1, &commit->tree->object, lock_token); + lock); +get_delta (sha1, &commit->tree->object, lock); }else if (obj->type == tree_type) {if (push_verbosely)fprintf (stderr,"walk %s\n" ,sha1_to_hex (obj->sha1)); -add_request (obj->sha1, lock_token); +add_request (obj->sha1, lock); tree = (struct tree *)obj;if (parse_tree (tree)) { fprintf(stderr, "Error parsing tree %s\n",
@@ -1324,17 +1413,18 @@ void get_delta(unsigned char *sha1, stru tree->entries =NULL ;while (entry) {struct tree_entry_list *next = entry->next; -get_delta (sha1, entry->item.any, lock_token); +get_delta (sha1, entry->item.any, lock);free (entry->name);free (entry); entry = next; } }else if (obj->type == blob_type || obj->type == tag_type) { -add_request (obj->sha1, lock_token); +add_request (obj->sha1, lock); } } -int update_remote (char *remote_path,unsigned char *sha1,char *lock_token) +int update_remote (char *remote_path,unsigned char *sha1, +struct active_lock *lock) {struct active_request_slot *slot;char *url;
@@ -1347,8 +1437,8 @@ int update_remote(char *remote_path, uns 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); + if_header =xmalloc (strlen (lock->token) +25 ); +sprintf (if_header,"If: (<opaquelocktoken:%s>)" , lock->token); dav_headers =curl_slist_append (dav_headers, if_header); out_buffer.size =41 ;
@@ -1411,7 +1501,7 @@ int main(int argc, char **argv)struct object *local_object =NULL ;char *remote_ref =NULL ;unsigned char remote_sha1[20 ]; -char *remote_lock =NULL ; +struct active_lock *remote_lock;char *remote_path =NULL ;char *low_speed_limit;char *low_speed_time;
@@ -1630,6 +1720,9 @@ int main(int argc, char **argv) unlock:unlock_remote (remote_path, remote_lock);free (remote_path); +if (remote_lock->owner !=NULL ) +free (remote_lock->owner); +free (remote_lock->token);free (remote_lock); }
---
0.99.9.GIT