You are viewing a plain text version of this content. The canonical link for it is here.
Posted to general@commons.apache.org by je...@apache.org on 2003/10/30 08:00:56 UTC
svn commit: rev 58 - in commons/serf/branches/gen2: . buckets test
Author: jerenkrantz
Date: Wed Oct 29 23:00:55 2003
New Revision: 58
Added:
commons/serf/branches/gen2/buckets/aggregate_buckets.c
commons/serf/branches/gen2/buckets/request_buckets.c
commons/serf/branches/gen2/test/
commons/serf/branches/gen2/test/serf_get.c
- copied, changed from rev 57, commons/serf/trunk/test/serf_get.c
Modified:
commons/serf/branches/gen2/buckets/buckets.c
commons/serf/branches/gen2/serf.h
commons/serf/branches/gen2/serf_bucket_types.h
Log:
Take a pass at the API and fleshing some things out. Implemented a few
files just to see if Greg and I are on the same page. We'll find out...
* test/serf_get.c (copied): Copied from trunk. This is a simple test
app that has some broken code for the new API.
* bucket/buckets.c (modified): Add a pool to serf_bucket_alloc_t,
define a primitive serf_metadata_t with just a hash, add set/get_metadata
defaults, implement the bucket_mem_alloc and bucket_mem_free calls.
* bucket/aggregate_buckets.c (new file): Add 'initial' aggregate buckets.
* bucket/request_buckets.c (new file): Add 'initial' request buckets.
* serf.h: Add serf_bucket_allocator_create() public declaration - notice
that I had it grow a pool. *shrug* See forthcoming STATUS commit...
* serf_bucket_types.h (SERF_REQUEST_HEADERS): Add 'public' metadata kind for
request bucket to set the HTTP headers.
Added: commons/serf/branches/gen2/buckets/aggregate_buckets.c
==============================================================================
--- (empty file)
+++ commons/serf/branches/gen2/buckets/aggregate_buckets.c Wed Oct 29 23:00:55 2003
@@ -0,0 +1,187 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include <apr_pools.h>
+
+#include "serf.h"
+#include "serf_bucket_util.h"
+
+/* Should be an APR_RING? */
+typedef struct bucket_list {
+ serf_bucket_t *bucket;
+ struct bucket_list *next;
+} bucket_list;
+
+typedef struct serf_aggregate_context_t {
+ bucket_list *list;
+} serf_aggregate_context_t;
+
+SERF_DECLARE(serf_bucket_t *) serf_bucket_aggregate_create(
+ serf_bucket_alloc_t *allocator)
+{
+ serf_aggregate_context_t *agg_context;
+
+ serf_bucket_mem_alloc(allocator, sizeof(*agg_context));
+
+ /* Theoretically, we *could* store this in the metadata of our bucket,
+ * but that'd be ridiculously slow.
+ */
+ agg_context->list = NULL;
+
+ return serf_bucket_create(serf_bucket_type_aggregate, allocator,
+ agg_context);
+}
+
+SERF_DECLARE(void) serf_bucket_aggregate_become(serf_bucket_t *bucket)
+{
+ /* Create a new bucket and swap their internal pointers? */
+}
+
+
+SERF_DECLARE(void) serf_bucket_aggregate_prepend(
+ serf_bucket_t *aggregate_bucket,
+ serf_bucket_t *prepend_bucket)
+{
+ serf_aggregate_context_t *agg_context;
+ bucket_list *new_bucket;
+
+ agg_context = (serf_aggregate_context_t*)aggregate_bucket->data;
+ new_bucket = serf_bucket_mem_alloc(aggregate_bucket->allocator,
+ sizeof(*bucket_list));
+
+ new_bucket->bucket = prepend_bucket;
+ new_bucket->next = agg_context->list;
+ agg_context->list = new_bucket;
+}
+
+SERF_DECLARE(void) serf_bucket_aggregate_append(
+ serf_bucket_t *aggregate_bucket,
+ serf_bucket_t *prepend_bucket)
+{
+ serf_aggregate_context_t *agg_context;
+ bucket_list *new_bucket;
+
+ agg_context = (serf_aggregate_context_t*)aggregate_bucket->data;
+ new_bucket = serf_bucket_mem_alloc(aggregate_bucket->allocator,
+ sizeof(*bucket_list));
+
+ /* If we use APR_RING, this is trivial. So, wait.
+ new_bucket->bucket = prepend_bucket;
+ new_bucket->next = agg_context->list;
+ agg_context->list = new_bucket;
+ */
+}
+
+static apr_status_t serf_aggregate_read(serf_bucket_t *bucket,
+ apr_size_t requested,
+ const char **data, apr_size_t *len)
+{
+ apr_status_t status;
+ serf_aggregate_context_t *agg_context;
+
+ agg_context = (serf_aggregate_context_t*)aggregate_bucket->data;
+ if (!agg_context->list) {
+ *len = 0;
+ return APR_SUCCESS;
+ }
+
+ status = serf_bucket_read(agg_context->list->bucket, requested, data, len);
+
+ /* Somehow, we need to know whether we're exhausted! */
+ if (!status && *len == 0) {
+ agg_context->list = agg_context->list->next;
+ /* Avoid recursive call here. Too lazy now. */
+ return serf_aggregate_read(bucket, request, data, len);
+ }
+
+ return status;
+}
+
+static apr_status_t serf_aggregate_readline(serf_bucket_t *bucket,
+ int acceptable, int *found,
+ const char **data, apr_size_t *len)
+{
+ /* Follow pattern from serf_aggregate_read. */
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t serf_aggregate_peek(serf_bucket_t *bucket,
+ const char **data,
+ apr_size_t *len)
+{
+ /* Follow pattern from serf_aggregate_read. */
+ return APR_ENOTIMPL;
+}
+
+static serf_bucket_t * serf_aggregate_read_bucket(serf_bucket_t *bucket,
+ serf_bucket_type_t *type)
+{
+ apr_status_t status;
+ serf_aggregate_context_t *agg_context;
+
+ agg_context = (serf_aggregate_context_t*)aggregate_bucket->data;
+ if (!agg_context->list) {
+ return NULL;
+ }
+
+ /* Call read_bucket on first one in our list. */
+ return serf_bucket_read_bucket(agg_context->list->bucket, type);
+}
+
+SERF_DECLARE_DATA serf_bucket_type_t serf_bucket_type_aggregate {
+ "AGGREGATE",
+ serf_aggregate_read,
+ serf_aggregate_readline,
+ serf_aggregate_peek,
+ serf_aggregate_read_bucket,
+ NULL, /* set_metadata */
+ NULL, /* get_metadata */
+ serf_default_destroy,
+};
Modified: commons/serf/branches/gen2/buckets/buckets.c
==============================================================================
--- commons/serf/branches/gen2/buckets/buckets.c (original)
+++ commons/serf/branches/gen2/buckets/buckets.c Wed Oct 29 23:00:55 2003
@@ -55,8 +55,12 @@
struct serf_bucket_alloc_t {
apr_allocator_t *allocator;
+ apr_pool_t *pool;
};
+struct serf_metadata_t {
+ apr_hash_t *hash;
+};
SERF_DECLARE(serf_bucket_t *) serf_bucket_create(
serf_bucket_type_t *type,
@@ -67,7 +71,8 @@
bkt->type = type;
bkt->data = data;
- bkt->metadata = NULL;
+ bkt->metadata = serf_bucket_mem_alloc(allocator, sizeof(*bkt->metadata));
+ bkt->metadata->hash = NULL;
bkt->allocator = allocator;
return bkt;
@@ -78,7 +83,27 @@
const char *md_name,
const void *md_value)
{
- return APR_ENOTIMPL;
+ apr_hash_t *md_hash;
+
+ md_hash = NULL;
+
+ if (!bucket->metadata->hash) {
+ bucket->metadata->hash = apr_hash_make(bucket->allocator->pool);
+ }
+ else {
+ md_hash = apr_hash_get(bucket->metadata->hash, md_type,
+ APR_HASH_KEY_STRING);
+ }
+
+ if (!md_hash) {
+ md_hash = apr_hash_make(bucket->allocator->pool);
+ apr_hash_set(bucket->metadata->hash, md_type, APR_HASH_KEY_STRING,
+ md_hash);
+ }
+
+ apr_hash_set(md_hash, md_name, APR_HASH_KEY_STRING, md_value);
+
+ return APR_SUCCESS;
}
@@ -87,7 +112,21 @@
const char *md_name,
const void **md_value)
{
- return APR_ENOTIMPL;
+ /* Initialize return value to not being found. */
+ *md_value = NULL;
+
+ if (bucket->metadata->hash) {
+ apr_hash_t *md_hash;
+
+ md_hash = apr_hash_get(bucket->metadata->hash, md_type,
+ APR_HASH_KEY_STRING);
+
+ if (md_hash) {
+ *md_value = apr_hash_get(md_hash, md_name, APR_HASH_KEY_STRING);
+ }
+ }
+
+ return APR_SUCCESS;
}
SERF_DECLARE(serf_bucket_t *) serf_default_read_bucket(
@@ -99,6 +138,7 @@
SERF_DECLARE(void) serf_default_destroy(serf_bucket_t *bucket)
{
+ serf_bucket_mem_free(bucket->allocator, bucket->metadata);
serf_bucket_mem_free(bucket->allocator, bucket);
}
@@ -107,12 +147,12 @@
SERF_DECLARE(serf_bucket_alloc_t *) serf_bucket_allocator_create(
- apr_allocator_t *allocator)
+ apr_allocator_t *allocator, apr_pool_t *pool)
{
serf_bucket_alloc_t *a = apr_allocator_alloc(allocator, sizeof(*a));
a->allocator = allocator;
-
+ a->pool = pool;
/* ### more */
return a;
@@ -121,6 +161,7 @@
SERF_DECLARE(void) serf_bucket_allocator_destroy(
serf_bucket_alloc_t *allocator)
{
+ /* We don't (yet) own the pool passed in to our allocator_create. */
apr_allocator_destroy(allocator->allocator);
}
@@ -128,13 +169,12 @@
serf_bucket_alloc_t *allocator,
apr_size_t size)
{
- /* ### need real code */
- return NULL;
+ return apr_allocator_alloc(allocator->allocator, size);
}
SERF_DECLARE(void) serf_bucket_mem_free(
serf_bucket_alloc_t *allocator,
void *block)
{
- /* ### need real code */
+ apr_allocator_free(allocator->allocator, block);
}
Added: commons/serf/branches/gen2/buckets/request_buckets.c
==============================================================================
--- (empty file)
+++ commons/serf/branches/gen2/buckets/request_buckets.c Wed Oct 29 23:00:55 2003
@@ -0,0 +1,169 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include <apr_pools.h>
+
+#include "serf.h"
+#include "serf_bucket_util.h"
+
+typedef enum serf_request_state_t {
+ UNREAD,
+ READING_STATUS,
+ READING_HEADERS,
+ READING_BODY,
+ EXHAUSTED
+} serf_request_state_t;
+
+typedef struct serf_request_context_t {
+ const char *method;
+ const char *uri;
+ serf_bucket_t *body;
+ serf_request_state_t state;
+} serf_request_context_t;
+
+SERF_DECLARE(serf_bucket_t *) serf_bucket_request_create(
+ const char *method,
+ const char *uri,
+ serf_bucket_t *body,
+ serf_bucket_alloc_t *allocator)
+{
+ serf_request_context_t *req_context;
+
+ serf_bucket_mem_alloc(allocator, sizeof(*req_context));
+
+ /* Theoretically, we *could* store this in the metadata of our bucket,
+ * but that'd be ridiculously slow.
+ */
+ req_context->method = method;
+ req_context->uri = uri;
+ req_context->body = body;
+ req_context->state = UNREAD;
+
+ return serf_bucket_create(serf_bucket_type_request, allocator, data);
+}
+
+static apr_status_t serf_request_read(serf_bucket_t *bucket,
+ apr_size_t requested,
+ const char **data, apr_size_t *len)
+{
+ serf_request_context_t *req_context;
+ serf_bucket_t *new_bucket;
+ const char *new_data;
+
+ req_context = (serf_request_context_t*)bucket->data;
+ new_bucket = NULL;
+
+ /* We'll store whatever we generate into a new bucket and update our
+ * state accordingly.
+ */
+ switch (req_context->state) {
+ case UNREAD:
+ /* Store method line. */
+ /* ARGH. Allocator needs to be public? */
+ new_data = apr_pstrcat(bucket->allocator->pool,
+ req_context->method, " ",
+ req_context->uri, " HTTP/1.1", NULL);
+ /* heap, pool, whatever. */
+ new_bucket = serf_bucket_pool_create(bucket->allocator, new_data);
+ req_context->state = READ_STATUS;
+ break;
+ case READ_STATUS:
+ /* Store method line. */
+ req_context->state = READ_HEADERS;
+ break;
+ case READ_HEADERS:
+ /* Return all headers. */
+ req_context->state = READ_BODY;
+ break;
+ case READ_BODY:
+ /* Just read from the body at this point! */
+ req_context->state = READ_EXHAUSTED;
+ break;
+ case EXHAUSTED:
+ /* Hmm. How did we get here? */
+ break;
+ }
+
+ if (!new_bucket) {
+ *len = 0;
+ return APR_SUCCESS;
+ }
+
+ /* Okay, so we created a bucket. Pass the 'hard' stuff to that bucket. */
+ /* This better have the semantics we want in that bucket is pushed down. */
+ serf_bucket_aggregate_become(bucket);
+ serf_bucket_aggregate_prepend(bucket, new_bucket);
+ return serf_bucket_read(bucket, data, len);
+}
+
+static apr_status_t serf_request_readline(serf_bucket_t *bucket,
+ int acceptable, int *found,
+ const char **data, apr_size_t *len)
+{
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t serf_request_peek(serf_bucket_t *bucket,
+ const char **data,
+ apr_size_t *len)
+{
+ return APR_ENOTIMPL;
+}
+
+SERF_DECLARE_DATA serf_bucket_type_t serf_bucket_type_request {
+ "REQUEST",
+ serf_request_read,
+ serf_request_readline,
+ serf_request_peek,
+ serf_default_read_bucket,
+ serf_default_set_metadata,
+ serf_default_get_metadata,
+ serf_default_destroy,
+};
Modified: commons/serf/branches/gen2/serf.h
==============================================================================
--- commons/serf/branches/gen2/serf.h (original)
+++ commons/serf/branches/gen2/serf.h Wed Oct 29 23:00:55 2003
@@ -58,6 +58,7 @@
#include <apr.h>
#include <apr_errno.h>
+#include <apr_allocator.h>
#include <apr_pools.h>
#include "serf_declare.h"
@@ -93,6 +94,13 @@
*/
SERF_DECLARE(serf_context_t *) serf_context_create(apr_pool_t *pool);
+/**
+ * Create a new allocator for buckets from an APR allocator.
+ *
+ * All buckets are associated with a serf bucket allocator.
+ */
+SERF_DECLARE(serf_bucket_alloc_t *) serf_bucket_allocator_create(
+ apr_allocator_t *allocator, apr_pool_t *pool);
/** @see serf_context_run should not block at all. */
#define SERF_DURATION_NOBLOCK 0
Modified: commons/serf/branches/gen2/serf_bucket_types.h
==============================================================================
--- commons/serf/branches/gen2/serf_bucket_types.h (original)
+++ commons/serf/branches/gen2/serf_bucket_types.h Wed Oct 29 23:00:55 2003
@@ -81,6 +81,8 @@
serf_bucket_t *body,
serf_bucket_alloc_t *allocator);
+/* Metadata key for get/set_metadata */
+#define SERF_REQUEST_HEADERS "REQUESTHEADERS"
/* ==================================================================== */
Copied: commons/serf/branches/gen2/test/serf_get.c (from rev 57, commons/serf/trunk/test/serf_get.c)
==============================================================================
--- commons/serf/trunk/test/serf_get.c (original)
+++ commons/serf/branches/gen2/test/serf_get.c Wed Oct 29 23:00:55 2003
@@ -270,18 +270,45 @@
return APR_SUCCESS;
}
+void closed_connection(serf_connection_t *conn,
+ void *closed_baton,
+ apr_status_t why,
+ apr_pool_t *pool)
+{
+
+}
+
+serf_bucket_t* accept_response(serf_connection_t *conn,
+ apr_socket_t *socket,
+ void *acceptor_baton,
+ apr_pool_t *respool,
+ apr_pool_t *tmppool)
+{
+
+}
+
+apr_status_t handle_response(serf_bucket_t *response,
+ void *handler_baton,
+ apr_pool_t *pool)
+{
+
+}
+
int main(int argc, const char **argv)
{
apr_status_t status;
apr_pool_t *pool;
+ apr_allocator_t *allocator;
+ serf_bucket_alloc_t *serf_allocator;
+ serf_context_t *context;
serf_connection_t *connection;
- serf_request_t *request;
+ serf_bucket_t *request;
serf_response_t *response;
serf_filter_t *filter;
apr_uri_t *url;
const char *raw_url;
int using_ssl = 0;
-
+
if (argc != 2) {
puts("Gimme a URL, stupid!");
exit(-1);
@@ -330,6 +357,40 @@
using_ssl = 1;
}
#endif
+
+ context = serf_context_create(pool);
+ status = apr_allocator_create(&allocator);
+ if (status) {
+ printf("Error: %d\n", status);
+ exit(status);
+ }
+
+ serf_allocator = serf_bucket_allocator_create(allocator, pool);
+
+ connection = serf_connection_create(context, address, accept_response,
+ NULL, closed_connection, NULL, pool);
+
+ request = serf_bucket_request_create("GET", url->path, NULL,
+ serf_allocator);
+
+ serf_bucket_set_metadata(request, SERF_REQUEST_HEADERS, "User-Agent",
+ "Serf" SERF_VERSION_STRING);
+
+ status = serf_connection_request_create(connection, request,
+ handle_response, NULL,
+ serf_allocator, pool);
+
+ if (status) {
+ printf("Error: %d\n", status);
+ exit(status);
+ }
+
+ status = serf_context_run(context, SERF_DURATION_FOREVER, pool);
+
+ if (status) {
+ printf("Error: %d\n", status);
+ exit(status);
+ }
status = serf_open_uri(url, &connection, &request, pool);