diff options
author | Bryan Ischo <bryan@ischo.com> | 2008-07-15 10:57:11 +0000 |
---|---|---|
committer | Bryan Ischo <bryan@ischo.com> | 2008-07-15 10:57:11 +0000 |
commit | ea2a15ab911ab49bccd30b9abd28b0fd8743972c (patch) | |
tree | 1e5d4b14b0215a3046e1999f9651021832cde182 | |
parent | feee3c65cfa74ba4a55b9726df5438aaa5b31ac1 (diff) | |
download | ceph-libs3-ea2a15ab911ab49bccd30b9abd28b0fd8743972c.tar.gz |
* S3RequestContext is now code complete, haven't tested it yet though
-rw-r--r-- | inc/libs3.h | 29 | ||||
-rw-r--r-- | inc/request.h | 5 | ||||
-rw-r--r-- | inc/request_context.h | 3 | ||||
-rw-r--r-- | src/general.c | 15 | ||||
-rw-r--r-- | src/request.c | 13 | ||||
-rw-r--r-- | src/request_context.c | 76 | ||||
-rw-r--r-- | src/s3.c | 12 |
7 files changed, 121 insertions, 32 deletions
diff --git a/inc/libs3.h b/inc/libs3.h index 808fd6d..2a94eed 100644 --- a/inc/libs3.h +++ b/inc/libs3.h @@ -34,7 +34,7 @@ * * xxx todo * NOTE: Response headers from Amazon S3 are limited to 4K (2K of metas is all - * that Amazon supports, and Amazon is allowed an additional 2K of headers). + * that Amazon supports, and libs3 allows Amazon an additional 2K of headers). * * Threading * --------- @@ -59,26 +59,26 @@ * style requests will prepend the bucket name to this host name, and * path-style requests will use this hostname directly **/ -#define S3_HOSTNAME "s3.amazonaws.com" +#define S3_HOSTNAME "s3.amazonaws.com" /** * S3_MAX_KEY_SIZE is the maximum size of keys that Amazon S3 supports. **/ -#define S3_MAX_KEY_SIZE 1024 +#define S3_MAX_KEY_SIZE 1024 /** * S3_MAX_METADATA_SIZE is the maximum number of bytes allowed for * x-amz-meta header names and values in any request passed to Amazon S3 **/ -#define S3_MAX_METADATA_SIZE 2048 +#define S3_MAX_METADATA_SIZE 2048 /** * S3_METADATA_HEADER_NAME_PREFIX is the prefix of an S3 "meta header" **/ -#define S3_METADATA_HEADER_NAME_PREFIX "x-amz-meta-" +#define S3_METADATA_HEADER_NAME_PREFIX "x-amz-meta-" /** @@ -97,28 +97,28 @@ * set on a bucket or object at one time. It is also the maximum number of * ACL grants that the XML ACL parsing routine will parse. **/ -#define S3_MAX_ACL_GRANT_COUNT 100 +#define S3_MAX_ACL_GRANT_COUNT 100 /** * This is the maximum number of characters (including terminating \0) that * libs3 supports in an ACL grantee email address. **/ -#define MAX_GRANTEE_EMAIL_ADDRESS_SIZE 128 +#define S3_MAX_GRANTEE_EMAIL_ADDRESS_SIZE 128 /** * This is the maximum number of characters (including terminating \0) that * libs3 supports in an ACL grantee user id. **/ -#define MAX_GRANTEE_USER_ID_SIZE 128 +#define S3_MAX_GRANTEE_USER_ID_SIZE 128 /** * This is the maximum number of characters (including terminating \0) that * libs3 supports in an ACL grantee user display name. **/ -#define MAX_GRANTEE_DISPLAY_NAME_SIZE 128 +#define S3_MAX_GRANTEE_DISPLAY_NAME_SIZE 128 /** ************************************************************************** @@ -136,6 +136,7 @@ typedef enum // being read S3StatusFailure , S3StatusOutOfMemory , + S3StatusInterrupted , S3StatusFailedToCreateMutex , S3StatusInvalidBucketNameTooLong , S3StatusInvalidBucketNameFirstCharacter , @@ -435,7 +436,7 @@ typedef struct S3AclGrant * This is the email address of the Amazon Customer being granted * permissions by this S3AclGrant. **/ - char emailAddress[MAX_GRANTEE_EMAIL_ADDRESS_SIZE]; + char emailAddress[S3_MAX_GRANTEE_EMAIL_ADDRESS_SIZE]; } amazonCustomerByEmail; /** * This structure is used iff the granteeType is @@ -446,11 +447,11 @@ typedef struct S3AclGrant /** * This is the CanonicalUser ID of the grantee **/ - char id[MAX_GRANTEE_USER_ID_SIZE]; + char id[S3_MAX_GRANTEE_USER_ID_SIZE]; /** * This is the display name of the grantee **/ - char displayName[MAX_GRANTEE_DISPLAY_NAME_SIZE]; + char displayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; } canonicalUser; } grantee; /** @@ -899,6 +900,10 @@ S3Status S3_runall_request_context(S3RequestContext *requestContext); S3Status S3_runonce_request_context(S3RequestContext *requestContext, int *requestsRemainingReturn); +S3Status S3_get_request_context_fdsets(S3RequestContext *requestContext, + fd_set *readFdSet, fd_set *writeFdSet, + fd_set *exceptFdSet, int *maxFd); + /* // xxx todo the function for getting the fdsets */ diff --git a/inc/request.h b/inc/request.h index 32e65d6..43850ff 100644 --- a/inc/request.h +++ b/inc/request.h @@ -117,6 +117,11 @@ typedef struct RequestParams // (and thus live while a curl_multi is in use). typedef struct Request { + // These put the request on a doubly-linked list of requests in a + // request context, *if* the request is in a request context (else these + // will both be 0) + struct Request *prev, *next; + // The status of this Request, as will be reported to the user via the // complete callback S3Status status; diff --git a/inc/request_context.h b/inc/request_context.h index 0d9d8b3..2cef70c 100644 --- a/inc/request_context.h +++ b/inc/request_context.h @@ -27,12 +27,11 @@ #include "libs3.h" - struct S3RequestContext { CURLM *curlm; - int count; + struct Request *requests; }; diff --git a/src/general.c b/src/general.c index b34a825..4915b0e 100644 --- a/src/general.c +++ b/src/general.c @@ -175,6 +175,7 @@ const char *S3_get_status_name(S3Status status) handlecase(OK); handlecase(Failure); handlecase(OutOfMemory); + handlecase(Interrupted); handlecase(FailedToCreateMutex); handlecase(InvalidBucketNameTooLong); handlecase(InvalidBucketNameFirstCharacter); @@ -365,9 +366,9 @@ typedef struct ConvertAclData int *aclGrantCountReturn; S3AclGrant *aclGrants; - string_buffer(emailAddress, MAX_GRANTEE_EMAIL_ADDRESS_SIZE); - string_buffer(userId, MAX_GRANTEE_USER_ID_SIZE); - string_buffer(userDisplayName, MAX_GRANTEE_DISPLAY_NAME_SIZE); + string_buffer(emailAddress, S3_MAX_GRANTEE_EMAIL_ADDRESS_SIZE); + string_buffer(userId, S3_MAX_GRANTEE_USER_ID_SIZE); + string_buffer(userDisplayName, S3_MAX_GRANTEE_DISPLAY_NAME_SIZE); string_buffer(groupUri, 128); string_buffer(permission, 32); } ConvertAclData; @@ -385,9 +386,9 @@ static S3Status convertAclXmlCallback(const char *elementPath, if (!strcmp(elementPath, "AccessControlPolicy/Owner/ID")) { caData->ownerIdLen += snprintf(&(caData->ownerId[caData->ownerIdLen]), - MAX_GRANTEE_USER_ID_SIZE - caData->ownerIdLen - 1, + S3_MAX_GRANTEE_USER_ID_SIZE - caData->ownerIdLen - 1, "%.*s", dataLen, data); - if (caData->ownerIdLen >= MAX_GRANTEE_USER_ID_SIZE) { + if (caData->ownerIdLen >= S3_MAX_GRANTEE_USER_ID_SIZE) { return S3StatusBadAclUserIdTooLong; } } @@ -396,11 +397,11 @@ static S3Status convertAclXmlCallback(const char *elementPath, caData->ownerDisplayNameLen += snprintf(&(caData->ownerDisplayName [caData->ownerDisplayNameLen]), - MAX_GRANTEE_DISPLAY_NAME_SIZE - + S3_MAX_GRANTEE_DISPLAY_NAME_SIZE - caData->ownerDisplayNameLen - 1, "%.*s", dataLen, data); if (caData->ownerDisplayNameLen >= - MAX_GRANTEE_DISPLAY_NAME_SIZE) { + S3_MAX_GRANTEE_DISPLAY_NAME_SIZE) { return S3StatusBadAclUserDisplayNameTooLong; } } diff --git a/src/request.c b/src/request.c index ee0c9a4..32776d5 100644 --- a/src/request.c +++ b/src/request.c @@ -769,6 +769,9 @@ static S3Status setup_curl(Request *request, // Debugging only // curl_easy_setopt_safe(CURLOPT_VERBOSE, 1); + // Set private data to request for the benefit of S3RequestContext + curl_easy_setopt_safe(CURLOPT_PRIVATE, request); + // Set header callback and data curl_easy_setopt_safe(CURLOPT_HEADERDATA, request); curl_easy_setopt_safe(CURLOPT_HEADERFUNCTION, &curl_header_func); @@ -921,6 +924,7 @@ static S3Status request_get(const RequestParams *params, } // Initialize the request + request->prev = request->next = 0; // Request status is initialized to no error, will be updated whenever // an error occurs @@ -1091,6 +1095,15 @@ void request_perform(const RequestParams *params, S3RequestContext *context) if (context) { switch (curl_multi_add_handle(context->curlm, request->curl)) { case CURLM_OK: + if (context->requests) { + request->prev = context->requests->prev; + request->next = context->requests; + context->requests->prev->next = + context->requests->prev = request; + } + else { + context->requests = request->next = request->prev = request; + } break; default: // This isn't right. Figure this out. diff --git a/src/request_context.c b/src/request_context.c index 1d298cf..69a6f37 100644 --- a/src/request_context.c +++ b/src/request_context.c @@ -23,28 +23,71 @@ ************************************************************************** **/ #include <curl/curl.h> +#include <stdlib.h> +#include <sys/select.h> #include "request.h" #include "request_context.h" S3Status S3_create_request_context(S3RequestContext **requestContextReturn) { - return ((*requestContextReturn = (S3RequestContext *) curl_multi_init()) ? - S3StatusOK : S3StatusFailedToCreateRequestContext); + *requestContextReturn = + (S3RequestContext *) malloc(sizeof(S3RequestContext)); + + if (!*requestContextReturn) { + return S3StatusFailedToCreateRequestContext; + } + + if (!((*requestContextReturn)->curlm = curl_multi_init())) { + free(*requestContextReturn); + return S3StatusOutOfMemory; + } + + (*requestContextReturn)->requests = 0; + + return S3StatusOK; } void S3_destroy_request_context(S3RequestContext *requestContext) { curl_multi_cleanup(requestContext->curlm); + + // For each request in the context, call back its done method with + // 'interrupted' status + Request *r = requestContext->requests, *rFirst = r; + + if (r) do { + r->status = S3StatusInterrupted; + Request *rNext = r->next; + request_finish(r); + r = rNext; + } while (r != rFirst); + + free(requestContext); } S3Status S3_runall_request_context(S3RequestContext *requestContext) { - // This should use the socket stuff to watch the fds and run only - // when there is data ready - return S3StatusFailure; + int requestsRemaining; + do { + fd_set readfds, writefds, 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); + status = S3_runonce_request_context(requestContext, + &requestsRemaining); + if (status != S3StatusOK) { + return status; + } + } while (requestsRemaining); + + return S3StatusOK; } @@ -59,6 +102,7 @@ S3Status S3_runonce_request_context(S3RequestContext *requestContext, switch (status) { case CURLM_OK: + case CURLM_CALL_MULTI_PERFORM: break; case CURLM_OUT_OF_MEMORY: return S3StatusOutOfMemory; @@ -79,6 +123,19 @@ S3Status S3_runonce_request_context(S3RequestContext *requestContext, (char **) &request) != CURLE_OK) { return S3StatusFailure; } + // Remove the request from the list of requests + if (request->prev == request->next) { + // It was the only one on the list + requestContext->requests = 0; + } + else { + // It doesn't matter what the order of them are, so just in + // case request was at the head of the list, put the one after + // request to the head of the list + requestContext->requests = request->next; + request->prev->next = request->next; + request->next->prev = request->prev; + } // Make response complete callback switch (msg->data.result) { case CURLE_OK: @@ -97,3 +154,12 @@ S3Status S3_runonce_request_context(S3RequestContext *requestContext, return S3StatusOK; } + +S3Status S3_get_request_context_fdsets(S3RequestContext *requestContext, + fd_set *readFdSet, fd_set *writeFdSet, + fd_set *exceptFdSet, int *maxFd) +{ + return ((curl_multi_fdset(requestContext->curlm, readFdSet, writeFdSet, + exceptFdSet, maxFd) == CURLM_OK) ? + S3StatusOK : S3StatusFailure); +} @@ -502,10 +502,10 @@ static S3Status convert_simple_acl(char *aclXml, char *ownerId, if (!strncmp(aclXml, "OwnerID", sizeof("OwnerID") - 1)) { aclXml += sizeof("OwnerID") - 1; - COPY_STRING_MAXLEN(ownerId, MAX_GRANTEE_USER_ID_SIZE); + COPY_STRING_MAXLEN(ownerId, S3_MAX_GRANTEE_USER_ID_SIZE); SKIP_SPACE(1); COPY_STRING_MAXLEN(ownerDisplayName, - MAX_GRANTEE_DISPLAY_NAME_SIZE); + S3_MAX_GRANTEE_DISPLAY_NAME_SIZE); continue; } @@ -1746,8 +1746,8 @@ void get_acl(int argc, char **argv, int optind) int aclGrantCount; S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - char ownerId[MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[MAX_GRANTEE_DISPLAY_NAME_SIZE]; + char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; + char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; S3_init(); @@ -1877,8 +1877,8 @@ void set_acl(int argc, char **argv, int optind) // Read in the complete ACL char aclBuf[65536]; aclBuf[fread(aclBuf, 1, sizeof(aclBuf), infile)] = 0; - char ownerId[MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[MAX_GRANTEE_DISPLAY_NAME_SIZE]; + char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; + char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; // Parse it int aclGrantCount; |