From 8cc18cbb67d459076d6d3df08b02c531d5ccc08f Mon Sep 17 00:00:00 2001 From: Bryan Ischo Date: Sun, 28 Sep 2008 05:08:56 +0000 Subject: * Remove time_t from API, replace with int64_t, which is of known size and avoids problems with structure sizes of precompiled libraries differing from that of compiled programs using libs3 * Fixed S3RequestContext functionality; it was untested and nonworking before this change * Added S3_get_request_context_timeout function for allowing callers to assist libs3 to support curl internal timeouts --- src/object.c | 4 ++-- src/request.c | 12 ++++++------ src/request_context.c | 35 ++++++++++++++++++++++++++++++----- src/s3.c | 23 +++++++++++++---------- src/util.c | 4 ++-- 5 files changed, 53 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/object.c b/src/object.c index dd77c61..0f33655 100644 --- a/src/object.c +++ b/src/object.c @@ -80,7 +80,7 @@ typedef struct CopyObjectData S3ResponseCompleteCallback *responseCompleteCallback; void *callbackData; - time_t *lastModifiedReturn; + int64_t *lastModifiedReturn; int eTagReturnSize; char *eTagReturn; int eTagReturnLen; @@ -165,7 +165,7 @@ static void copyObjectCompleteCallback(S3Status requestStatus, void S3_copy_object(const S3BucketContext *bucketContext, const char *key, const char *destinationBucket, const char *destinationKey, const S3PutProperties *putProperties, - time_t *lastModifiedReturn, int eTagReturnSize, + int64_t *lastModifiedReturn, int eTagReturnSize, char *eTagReturn, S3RequestContext *requestContext, const S3ResponseHandler *handler, void *callbackData) { diff --git a/src/request.c b/src/request.c index d5b455e..79837fa 100644 --- a/src/request.c +++ b/src/request.c @@ -431,9 +431,9 @@ static S3Status compose_standard_headers(const RequestParams *params, // Expires if (params->putProperties && (params->putProperties->expires >= 0)) { + time_t t = (time_t) params->putProperties->expires; strftime(values->expiresHeader, sizeof(values->expiresHeader), - "Expires: %a, %d %b %Y %H:%M:%S UTC", - gmtime(&(params->putProperties->expires))); + "Expires: %a, %d %b %Y %H:%M:%S UTC", gmtime(&t)); } else { values->expiresHeader[0] = 0; @@ -442,10 +442,10 @@ static S3Status compose_standard_headers(const RequestParams *params, // If-Modified-Since if (params->getConditions && (params->getConditions->ifModifiedSince >= 0)) { + time_t t = (time_t) params->getConditions->ifModifiedSince; strftime(values->ifModifiedSinceHeader, sizeof(values->ifModifiedSinceHeader), - "If-Modified-Since: %a, %d %b %Y %H:%M:%S UTC", - gmtime(&(params->getConditions->ifModifiedSince))); + "If-Modified-Since: %a, %d %b %Y %H:%M:%S UTC", gmtime(&t)); } else { values->ifModifiedSinceHeader[0] = 0; @@ -454,10 +454,10 @@ static S3Status compose_standard_headers(const RequestParams *params, // If-Unmodified-Since header if (params->getConditions && (params->getConditions->ifNotModifiedSince >= 0)) { + time_t t = (time_t) params->getConditions->ifNotModifiedSince; strftime(values->ifUnmodifiedSinceHeader, sizeof(values->ifUnmodifiedSinceHeader), - "If-Unmodified-Since: %a, %d %b %Y %H:%M:%S UTC", - gmtime(&(params->getConditions->ifNotModifiedSince))); + "If-Unmodified-Since: %a, %d %b %Y %H:%M:%S UTC", gmtime(&t)); } else { values->ifUnmodifiedSinceHeader[0] = 0; diff --git a/src/request_context.c b/src/request_context.c index 567f51a..d049778 100644 --- a/src/request_context.c +++ b/src/request_context.c @@ -75,13 +75,25 @@ S3Status S3_runall_request_context(S3RequestContext *requestContext) int requestsRemaining; do { fd_set readfds, writefds, exceptfds; + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); int maxfd; S3Status status = S3_get_request_context_fdsets (requestContext, &readfds, &writefds, &exceptfds, &maxfd); if (status != S3StatusOK) { return status; } - select(maxfd + 1, &readfds, &writefds, &exceptfds, 0); + // curl will return -1 if it hasn't even created any fds yet because + // none of the connections have started yet. In this case, don't + // do the select at all, because it will wait forever; instead, just + // skip it and go straight to running the underlying CURL handles + if (maxfd != -1) { + int64_t timeout = S3_get_request_context_timeout(requestContext); + struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 }; + select(maxfd + 1, &readfds, &writefds, &exceptfds, + (timeout == -1) ? 0 : &tv); + } status = S3_runonce_request_context(requestContext, &requestsRemaining); if (status != S3StatusOK) { @@ -115,13 +127,11 @@ S3Status S3_runonce_request_context(S3RequestContext *requestContext, CURLMsg *msg; int junk; while ((msg = curl_multi_info_read(requestContext->curlm, &junk))) { - if ((msg->msg != CURLMSG_DONE) || - (curl_multi_remove_handle(requestContext->curlm, - msg->easy_handle) != CURLM_OK)) { + if (msg->msg != CURLMSG_DONE) { return S3StatusInternalError; } Request *request; - if (curl_easy_getinfo(msg->easy_handle, CURLOPT_PRIVATE, + if (curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, (char *) &request) != CURLE_OK) { return S3StatusInternalError; } @@ -143,6 +153,10 @@ S3Status S3_runonce_request_context(S3RequestContext *requestContext, request->status = request_curl_code_to_status (msg->data.result); } + if (curl_multi_remove_handle(requestContext->curlm, + msg->easy_handle) != CURLM_OK) { + return S3StatusInternalError; + } // Finish the request, ensuring that all callbacks have been made, // and also releases the request request_finish(request); @@ -160,3 +174,14 @@ S3Status S3_get_request_context_fdsets(S3RequestContext *requestContext, exceptFdSet, maxFd) == CURLM_OK) ? S3StatusOK : S3StatusInternalError); } + +int64_t S3_get_request_context_timeout(S3RequestContext *requestContext) +{ + long timeout; + + if (curl_multi_timeout(requestContext->curlm, &timeout) != CURLM_OK) { + timeout = 0; + } + + return timeout; +} diff --git a/src/s3.c b/src/s3.c index 895c0c7..55ee2ac 100644 --- a/src/s3.c +++ b/src/s3.c @@ -696,9 +696,9 @@ static S3Status responsePropertiesCallback print_nonnull("ETag", eTag); if (properties->lastModified > 0) { char timebuf[256]; + time_t t = (time_t) properties->lastModified; // gmtime is not thread-safe but we don't care here. - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&(properties->lastModified))); + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); printf("Last-Modified: %s\n", timebuf); } int i; @@ -782,7 +782,7 @@ static void printListServiceHeader(int allDetails) static S3Status listServiceCallback(const char *ownerId, const char *ownerDisplayName, const char *bucketName, - time_t creationDate, void *callbackData) + int64_t creationDate, void *callbackData) { list_service_data *data = (list_service_data *) callbackData; @@ -793,8 +793,8 @@ static S3Status listServiceCallback(const char *ownerId, char timebuf[256]; if (creationDate >= 0) { - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&creationDate)); + time_t t = (time_t) creationDate; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); } else { timebuf[0] = 0; @@ -1090,8 +1090,9 @@ static S3Status listBucketCallback(int isTruncated, const char *nextMarker, const S3ListBucketContent *content = &(contents[i]); char timebuf[256]; if (0) { + time_t t = (time_t) content->lastModified; strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&(content->lastModified))); + gmtime(&t)); printf("\nKey: %s\n", content->key); printf("Last Modified: %s\n", timebuf); printf("ETag: %s\n", content->eTag); @@ -1104,8 +1105,9 @@ static S3Status listBucketCallback(int isTruncated, const char *nextMarker, } } else { - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&(content->lastModified))); + time_t t = (time_t) content->lastModified; + strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", + gmtime(&t)); char sizebuf[16]; if (content->size < 100000) { sprintf(sizebuf, "%5llu", (unsigned long long) content->size); @@ -1749,7 +1751,7 @@ static void copy_object(int argc, char **argv, int optind) &responseCompleteCallback }; - time_t lastModified; + int64_t lastModified; char eTag[256]; do { @@ -1762,8 +1764,9 @@ static void copy_object(int argc, char **argv, int optind) if (statusG == S3StatusOK) { if (lastModified >= 0) { char timebuf[256]; + time_t t = (time_t) lastModified; strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&lastModified)); + gmtime(&t)); printf("Last-Modified: %s\n", timebuf); } if (eTag[0]) { diff --git a/src/util.c b/src/util.c index 4557d0e..613f695 100644 --- a/src/util.c +++ b/src/util.c @@ -95,7 +95,7 @@ int urlEncode(char *dest, const char *src, int maxSrcSize) } -time_t parseIso8601Time(const char *str) +int64_t parseIso8601Time(const char *str) { // Check to make sure that it has a valid format if (!checkString(str, "dddd-dd-ddTdd:dd:dd")) { @@ -130,7 +130,7 @@ time_t parseIso8601Time(const char *str) stm.tm_isdst = -1; - time_t ret = mktime(&stm); + int64_t ret = mktime(&stm); // Skip the millis -- cgit v1.2.1