]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/subversion/subversion/libsvn_ra_serf/sb_bucket.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / subversion / subversion / libsvn_ra_serf / sb_bucket.c
1 /*
2  * sb_bucket.c :  a serf bucket that wraps a spillbuf
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23
24 #include <serf.h>
25 #include <serf_bucket_util.h>
26
27 #include "svn_private_config.h"
28 #include "private/svn_subr_private.h"
29
30 #include "ra_serf.h"
31
32 #define SB_BLOCKSIZE 1024
33 #define SB_MAXSIZE 32768
34
35
36 struct sbb_baton
37 {
38   svn_spillbuf_t *spillbuf;
39
40   const char *holding;
41   apr_size_t hold_len;
42
43   apr_pool_t *scratch_pool;
44 };
45
46
47 svn_error_t *
48 svn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf,
49                                 serf_bucket_t *bkt,
50                                 apr_pool_t *result_pool,
51                                 apr_pool_t *scratch_pool)
52 {
53   *spillbuf = svn_spillbuf__create(SB_BLOCKSIZE, SB_MAXSIZE, result_pool);
54
55   /* Copy all data from the bucket into the spillbuf.  */
56   while (TRUE)
57     {
58       apr_status_t status;
59       const char *data;
60       apr_size_t len;
61
62       status = serf_bucket_read(bkt, SERF_READ_ALL_AVAIL, &data, &len);
63
64       if (status != APR_SUCCESS && status != APR_EOF)
65         return svn_ra_serf__wrap_err(status, _("Failed to read the request"));
66
67       SVN_ERR(svn_spillbuf__write(*spillbuf, data, len, scratch_pool));
68
69       if (status == APR_EOF)
70         break;
71     }
72
73   return SVN_NO_ERROR;
74 }
75
76
77 static apr_status_t
78 sb_bucket_read(serf_bucket_t *bucket, apr_size_t requested,
79                const char **data, apr_size_t *len)
80 {
81   struct sbb_baton *sbb = bucket->data;
82   svn_error_t *err;
83
84   if (sbb->holding)
85     {
86       *data = sbb->holding;
87
88       if (requested < sbb->hold_len)
89         {
90           *len = requested;
91           sbb->holding += requested;
92           sbb->hold_len -= requested;
93           return APR_SUCCESS;
94         }
95
96       /* Return whatever we're holding, and then forget (consume) it.  */
97       *len = sbb->hold_len;
98       sbb->holding = NULL;
99       return APR_SUCCESS;
100     }
101
102   err = svn_spillbuf__read(data, len, sbb->spillbuf, sbb->scratch_pool);
103   svn_pool_clear(sbb->scratch_pool);
104
105   /* ### do something with this  */
106   svn_error_clear(err);
107
108   /* The spillbuf may have returned more than requested. Stash any extra
109      into our holding area.  */
110   if (requested < *len)
111     {
112       sbb->holding = *data + requested;
113       sbb->hold_len = *len - requested;
114       *len = requested;
115     }
116
117   return *data == NULL ? APR_EOF : APR_SUCCESS;
118 }
119
120
121 static apr_status_t
122 sb_bucket_readline(serf_bucket_t *bucket, int acceptable,
123                    int *found,
124                    const char **data, apr_size_t *len)
125 {
126   /* ### for now, we know callers won't use this function.  */
127   svn_error_clear(svn_error__malfunction(TRUE, __FILE__, __LINE__,
128                                          "Not implemented."));
129   return APR_ENOTIMPL;
130 }
131
132
133 static apr_status_t
134 sb_bucket_peek(serf_bucket_t *bucket,
135                const char **data, apr_size_t *len)
136 {
137   struct sbb_baton *sbb = bucket->data;
138   svn_error_t *err;
139
140   /* If we're not holding any data, then fill it.  */
141   if (sbb->holding == NULL)
142     {
143       err = svn_spillbuf__read(&sbb->holding, &sbb->hold_len, sbb->spillbuf,
144                                sbb->scratch_pool);
145       svn_pool_clear(sbb->scratch_pool);
146
147       /* ### do something with this  */
148       svn_error_clear(err);
149     }
150
151   /* Return the data we are (now) holding.  */
152   *data = sbb->holding;
153   *len = sbb->hold_len;
154
155   return *data == NULL ? APR_EOF : APR_SUCCESS;
156 }
157
158
159 static const serf_bucket_type_t sb_bucket_vtable = {
160     "SPILLBUF",
161     sb_bucket_read,
162     sb_bucket_readline,
163     serf_default_read_iovec,
164     serf_default_read_for_sendfile,
165     serf_default_read_bucket,
166     sb_bucket_peek,
167     serf_default_destroy_and_data,
168 };
169
170
171 serf_bucket_t *
172 svn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf,
173                               serf_bucket_alloc_t *allocator,
174                               apr_pool_t *result_pool,
175                               apr_pool_t *scratch_pool)
176 {
177   struct sbb_baton *sbb;
178
179   sbb = serf_bucket_mem_alloc(allocator, sizeof(*sbb));
180   sbb->spillbuf = spillbuf;
181   sbb->holding = NULL;
182   sbb->scratch_pool = svn_pool_create(result_pool);
183
184   return serf_bucket_create(&sb_bucket_vtable, allocator, sbb);
185 }