summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBryan Ischo <bryan@ischo.com>2008-07-15 10:57:11 +0000
committerBryan Ischo <bryan@ischo.com>2008-07-15 10:57:11 +0000
commitea2a15ab911ab49bccd30b9abd28b0fd8743972c (patch)
tree1e5d4b14b0215a3046e1999f9651021832cde182
parentfeee3c65cfa74ba4a55b9726df5438aaa5b31ac1 (diff)
downloadceph-libs3-ea2a15ab911ab49bccd30b9abd28b0fd8743972c.tar.gz
* S3RequestContext is now code complete, haven't tested it yet though
-rw-r--r--inc/libs3.h29
-rw-r--r--inc/request.h5
-rw-r--r--inc/request_context.h3
-rw-r--r--src/general.c15
-rw-r--r--src/request.c13
-rw-r--r--src/request_context.c76
-rw-r--r--src/s3.c12
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);
+}
diff --git a/src/s3.c b/src/s3.c
index fcbda8e..1691753 100644
--- a/src/s3.c
+++ b/src/s3.c
@@ -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;