~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr-util/test/testreslist.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
#include "apr_reslist.h"
 
20
#include "apr_thread_proc.h"
 
21
 
 
22
#if APR_HAVE_TIME_H
 
23
#include <time.h>
 
24
#endif /* APR_HAVE_TIME_H */
 
25
 
 
26
#if !APR_HAS_THREADS
 
27
 
 
28
int main(void)
 
29
{
 
30
    fprintf(stderr, "this program requires APR thread support\n");
 
31
    return 0;
 
32
}
 
33
 
 
34
#else
 
35
 
 
36
#define RESLIST_MIN   3
 
37
#define RESLIST_SMAX 10
 
38
#define RESLIST_HMAX 20
 
39
#define RESLIST_TTL  APR_TIME_C(350000) /* 35 ms */
 
40
#define CONSUMER_THREADS 25
 
41
#define CONSUMER_ITERATIONS 250
 
42
#define CONSTRUCT_SLEEP_TIME  APR_TIME_C(250000) /* 25 ms */
 
43
#define DESTRUCT_SLEEP_TIME   APR_TIME_C(100000) /* 10 ms */
 
44
#define WORK_DELAY_SLEEP_TIME APR_TIME_C(150000) /* 15 ms */
 
45
 
 
46
typedef struct {
 
47
    apr_interval_time_t sleep_upon_construct;
 
48
    apr_interval_time_t sleep_upon_destruct;
 
49
    int c_count;
 
50
    int d_count;
 
51
} my_parameters_t;
 
52
 
 
53
typedef struct {
 
54
    int id;
 
55
} my_resource_t;
 
56
 
 
57
static apr_status_t my_constructor(void **resource, void *params,
 
58
                                   apr_pool_t *pool)
 
59
{
 
60
    my_resource_t *res;
 
61
    my_parameters_t *my_params = params;
 
62
 
 
63
    /* Create some resource */
 
64
    res = apr_palloc(pool, sizeof(*res));
 
65
    res->id = my_params->c_count++;
 
66
 
 
67
    printf("++ constructing new resource [id:%d, #%d/%d]\n", res->id,
 
68
       my_params->c_count, my_params->d_count);
 
69
 
 
70
    /* Sleep for awhile, to simulate construction overhead. */
 
71
    apr_sleep(my_params->sleep_upon_construct);
 
72
 
 
73
    /* Set the resource so it can be managed by the reslist */
 
74
    *resource = res;
 
75
    return APR_SUCCESS;
 
76
}
 
77
 
 
78
static apr_status_t my_destructor(void *resource, void *params,
 
79
                                  apr_pool_t *pool)
 
80
{
 
81
    my_resource_t *res = resource;
 
82
    my_parameters_t *my_params = params;
 
83
 
 
84
    printf("-- destructing old resource [id:%d, #%d/%d]\n", res->id,
 
85
           my_params->c_count, ++my_params->d_count);
 
86
 
 
87
    apr_sleep(my_params->sleep_upon_destruct);
 
88
 
 
89
    return APR_SUCCESS;
 
90
}
 
91
 
 
92
typedef struct {
 
93
    int tid;
 
94
    apr_reslist_t *reslist;
 
95
    apr_interval_time_t work_delay_sleep;
 
96
} my_thread_info_t;
 
97
 
 
98
static void * APR_THREAD_FUNC resource_consuming_thread(apr_thread_t *thd,
 
99
                                                        void *data)
 
100
{
 
101
    apr_status_t rv;
 
102
    my_thread_info_t *thread_info = data;
 
103
    apr_reslist_t *rl = thread_info->reslist;
 
104
    int i;
 
105
 
 
106
    for (i = 0; i < CONSUMER_ITERATIONS; i++) {
 
107
        my_resource_t *res;
 
108
        void *vp;
 
109
        rv = apr_reslist_acquire(rl, &vp);
 
110
        if (rv != APR_SUCCESS) {
 
111
            fprintf(stderr, "Failed to retrieve resource from reslist\n");
 
112
            apr_thread_exit(thd, rv);
 
113
            return NULL;
 
114
        }
 
115
        res = vp;
 
116
        printf("  [tid:%d,iter:%d] using resource id:%d\n", thread_info->tid,
 
117
               i, res->id);
 
118
        apr_sleep(thread_info->work_delay_sleep);
 
119
/* simulate a 5% chance of the resource being bad */
 
120
        if ( drand48() < 0.95 ) {
 
121
           rv = apr_reslist_release(rl, res);
 
122
            if (rv != APR_SUCCESS) {
 
123
                fprintf(stderr, "Failed to return resource to reslist\n");
 
124
                apr_thread_exit(thd, rv);
 
125
                return NULL;
 
126
            }
 
127
       } else {
 
128
           printf("invalidating resource id:%d\n", res->id) ;
 
129
           rv = apr_reslist_invalidate(rl, res);
 
130
            if (rv != APR_SUCCESS) {
 
131
                fprintf(stderr, "Failed to invalidate resource\n");
 
132
                apr_thread_exit(thd, rv);
 
133
                return NULL;
 
134
            }
 
135
       }
 
136
    }
 
137
 
 
138
    return APR_SUCCESS;
 
139
}
 
140
 
 
141
static void test_timeout(apr_reslist_t *rl)
 
142
{
 
143
    apr_status_t rv;
 
144
    my_resource_t *resources[RESLIST_HMAX];
 
145
    my_resource_t *res;
 
146
    void *vp;
 
147
    int i;
 
148
 
 
149
    printf("Setting timeout to 1000us: ");
 
150
    apr_reslist_timeout_set(rl, 1000);
 
151
    fprintf(stdout, "OK\n");
 
152
 
 
153
    /* deplete all possible resources from the resource list 
 
154
     * so that the next call will block until timeout is reached 
 
155
     * (since there are no other threads to make a resource 
 
156
     * available)
 
157
     */
 
158
 
 
159
    for (i = 0; i < RESLIST_HMAX; i++) {
 
160
        rv = apr_reslist_acquire(rl, (void**)&resources[i]);
 
161
        if (rv != APR_SUCCESS) {
 
162
            fprintf(stderr, "couldn't acquire resource: %d\n", rv);
 
163
            exit(1);
 
164
        }
 
165
    }
 
166
 
 
167
    /* next call will block until timeout is reached */
 
168
    rv = apr_reslist_acquire(rl, &vp);
 
169
    if (!APR_STATUS_IS_TIMEUP(rv)) {
 
170
        fprintf(stderr, "apr_reslist_acquire()->%d instead of TIMEUP\n", 
 
171
                rv);
 
172
        exit(1);
 
173
    }
 
174
    res = vp;
 
175
 
 
176
    /* release the resources; otherwise the destroy operation
 
177
     * will blow
 
178
     */
 
179
    for (i = 0; i < RESLIST_HMAX; i++) {
 
180
        rv = apr_reslist_release(rl, &resources[i]);
 
181
        if (rv != APR_SUCCESS) {
 
182
            fprintf(stderr, "couldn't release resource: %d\n", rv);
 
183
            exit(1);
 
184
        }
 
185
    }
 
186
}
 
187
 
 
188
static apr_status_t test_reslist(apr_pool_t *parpool)
 
189
{
 
190
    apr_status_t rv;
 
191
    apr_pool_t *pool;
 
192
    apr_reslist_t *rl;
 
193
    my_parameters_t *params;
 
194
    int i;
 
195
    apr_thread_t *my_threads[CONSUMER_THREADS];
 
196
    my_thread_info_t my_thread_info[CONSUMER_THREADS];
 
197
    srand48(time(0)) ;
 
198
 
 
199
    printf("Creating child pool.......................");
 
200
    rv = apr_pool_create(&pool, parpool);
 
201
    if (rv != APR_SUCCESS) {
 
202
        fprintf(stderr, "Error creating child pool\n");
 
203
        return rv;
 
204
    }
 
205
    printf("OK\n");
 
206
 
 
207
    /* Create some parameters that will be passed into each
 
208
     * constructor and destructor call. */
 
209
    params = apr_pcalloc(pool, sizeof(*params));
 
210
    params->sleep_upon_construct = CONSTRUCT_SLEEP_TIME;
 
211
    params->sleep_upon_destruct = DESTRUCT_SLEEP_TIME;
 
212
 
 
213
    /* We're going to want 10 blocks of data from our target rmm. */
 
214
    printf("Creating resource list:\n"
 
215
           " min/smax/hmax: %d/%d/%d\n"
 
216
           " ttl: %" APR_TIME_T_FMT "\n", RESLIST_MIN, RESLIST_SMAX,
 
217
           RESLIST_HMAX, RESLIST_TTL);
 
218
    rv = apr_reslist_create(&rl, RESLIST_MIN, RESLIST_SMAX, RESLIST_HMAX,
 
219
                            RESLIST_TTL, my_constructor, my_destructor,
 
220
                            params, pool);
 
221
    if (rv != APR_SUCCESS) { 
 
222
        fprintf(stderr, "Error allocating shared memory block\n");
 
223
        return rv;
 
224
    }
 
225
    fprintf(stdout, "OK\n");
 
226
 
 
227
    printf("Creating %d threads", CONSUMER_THREADS);
 
228
    for (i = 0; i < CONSUMER_THREADS; i++) {
 
229
        putchar('.');
 
230
        my_thread_info[i].tid = i;
 
231
        my_thread_info[i].reslist = rl;
 
232
        my_thread_info[i].work_delay_sleep = WORK_DELAY_SLEEP_TIME;
 
233
        rv = apr_thread_create(&my_threads[i], NULL,
 
234
                               resource_consuming_thread, &my_thread_info[i],
 
235
                               pool);
 
236
        if (rv != APR_SUCCESS) {
 
237
            fprintf(stderr, "Failed to create thread %d\n", i);
 
238
            return rv;
 
239
        }
 
240
    }
 
241
    printf("\nDone!\n");
 
242
 
 
243
    printf("Waiting for threads to finish");
 
244
    for (i = 0; i < CONSUMER_THREADS; i++) {
 
245
        apr_status_t thread_rv;
 
246
        putchar('.');
 
247
        apr_thread_join(&thread_rv, my_threads[i]);
 
248
        if (rv != APR_SUCCESS) {
 
249
            fprintf(stderr, "Failed to join thread %d\n", i);
 
250
            return rv;
 
251
        }
 
252
    }
 
253
    printf("\nDone!\n");
 
254
 
 
255
    test_timeout(rl);
 
256
 
 
257
    printf("Destroying resource list.................");
 
258
    rv = apr_reslist_destroy(rl);
 
259
    if (rv != APR_SUCCESS) {
 
260
        printf("FAILED\n");
 
261
        return rv;
 
262
    }
 
263
    printf("OK\n");
 
264
 
 
265
    apr_pool_destroy(pool);
 
266
 
 
267
    return APR_SUCCESS;
 
268
}
 
269
 
 
270
 
 
271
int main(void)
 
272
{
 
273
    apr_status_t rv;
 
274
    apr_pool_t *pool;
 
275
    char errmsg[200];
 
276
 
 
277
    apr_initialize();
 
278
    
 
279
    printf("APR Resource List Test\n");
 
280
    printf("======================\n\n");
 
281
 
 
282
    printf("Initializing the pool............................"); 
 
283
    if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
 
284
        printf("could not initialize pool\n");
 
285
        exit(-1);
 
286
    }
 
287
    printf("OK\n");
 
288
 
 
289
    rv = test_reslist(pool);
 
290
    if (rv != APR_SUCCESS) {
 
291
        printf("Resource list test FAILED: [%d] %s\n",
 
292
               rv, apr_strerror(rv, errmsg, sizeof(errmsg)));
 
293
        exit(-2);
 
294
    }
 
295
    printf("Resource list test passed!\n");
 
296
 
 
297
    return 0;
 
298
}
 
299
 
 
300
#endif /* APR_HAS_THREADS */