~ubuntu-branches/ubuntu/precise/apr-util/precise

1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
 * contributor license agreements.  See the NOTICE file distributed with
3
 * this work for additional information regarding copyright ownership.
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * (the "License"); you may not use this file except in compliance with
6
 * the License.  You may obtain a copy of the License at
1 by Tollef Fog Heen
Import upstream version 1.2.7
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>
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
19
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
20
#include "apr_general.h"
21
#include "apu.h"
1 by Tollef Fog Heen
Import upstream version 1.2.7
22
#include "apr_reslist.h"
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
23
#include "apr_thread_pool.h"
24
1 by Tollef Fog Heen
Import upstream version 1.2.7
25
#if APR_HAVE_TIME_H
26
#include <time.h>
27
#endif /* APR_HAVE_TIME_H */
28
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
29
#include "abts.h"
30
#include "testutil.h"
31
32
#if APR_HAS_THREADS
1 by Tollef Fog Heen
Import upstream version 1.2.7
33
34
#define RESLIST_MIN   3
35
#define RESLIST_SMAX 10
36
#define RESLIST_HMAX 20
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
37
#define RESLIST_TTL  APR_TIME_C(35000) /* 35 ms */
1 by Tollef Fog Heen
Import upstream version 1.2.7
38
#define CONSUMER_THREADS 25
39
#define CONSUMER_ITERATIONS 250
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
40
#define CONSTRUCT_SLEEP_TIME  APR_TIME_C(25000) /* 25 ms */
41
#define DESTRUCT_SLEEP_TIME   APR_TIME_C(10000) /* 10 ms */
42
#define WORK_DELAY_SLEEP_TIME APR_TIME_C(15000) /* 15 ms */
1 by Tollef Fog Heen
Import upstream version 1.2.7
43
44
typedef struct {
45
    apr_interval_time_t sleep_upon_construct;
46
    apr_interval_time_t sleep_upon_destruct;
47
    int c_count;
48
    int d_count;
49
} my_parameters_t;
50
51
typedef struct {
52
    int id;
53
} my_resource_t;
54
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
55
/* Linear congruential generator */
56
static apr_uint32_t lgc(apr_uint32_t a)
57
{
58
    apr_uint64_t z = a;
59
    z *= 279470273;
60
    z %= APR_UINT64_C(4294967291);
61
    return (apr_uint32_t)z;
62
}
63
1 by Tollef Fog Heen
Import upstream version 1.2.7
64
static apr_status_t my_constructor(void **resource, void *params,
65
                                   apr_pool_t *pool)
66
{
67
    my_resource_t *res;
68
    my_parameters_t *my_params = params;
69
70
    /* Create some resource */
71
    res = apr_palloc(pool, sizeof(*res));
72
    res->id = my_params->c_count++;
73
74
    /* Sleep for awhile, to simulate construction overhead. */
75
    apr_sleep(my_params->sleep_upon_construct);
76
77
    /* Set the resource so it can be managed by the reslist */
78
    *resource = res;
79
    return APR_SUCCESS;
80
}
81
82
static apr_status_t my_destructor(void *resource, void *params,
83
                                  apr_pool_t *pool)
84
{
85
    my_resource_t *res = resource;
86
    my_parameters_t *my_params = params;
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
87
    res->id = my_params->d_count++;
1 by Tollef Fog Heen
Import upstream version 1.2.7
88
89
    apr_sleep(my_params->sleep_upon_destruct);
90
91
    return APR_SUCCESS;
92
}
93
94
typedef struct {
95
    int tid;
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
96
    abts_case *tc;
1 by Tollef Fog Heen
Import upstream version 1.2.7
97
    apr_reslist_t *reslist;
98
    apr_interval_time_t work_delay_sleep;
99
} my_thread_info_t;
100
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
101
/* MAX_UINT * .95 = 2**32 * .95 = 4080218931u */
102
#define PERCENT95th 4080218931u
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
103
1 by Tollef Fog Heen
Import upstream version 1.2.7
104
static void * APR_THREAD_FUNC resource_consuming_thread(apr_thread_t *thd,
105
                                                        void *data)
106
{
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
107
    int i;
108
    apr_uint32_t chance;
109
    void *vp;
1 by Tollef Fog Heen
Import upstream version 1.2.7
110
    apr_status_t rv;
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
111
    my_resource_t *res;
1 by Tollef Fog Heen
Import upstream version 1.2.7
112
    my_thread_info_t *thread_info = data;
113
    apr_reslist_t *rl = thread_info->reslist;
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
114
115
#if APR_HAS_RANDOM
116
    apr_generate_random_bytes((void*)&chance, sizeof(chance));
117
#else
118
    chance = (apr_uint32_t)(apr_time_now() % APR_TIME_C(4294967291));
119
#endif
1 by Tollef Fog Heen
Import upstream version 1.2.7
120
121
    for (i = 0; i < CONSUMER_ITERATIONS; i++) {
122
        rv = apr_reslist_acquire(rl, &vp);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
123
        ABTS_INT_EQUAL(thread_info->tc, APR_SUCCESS, rv);
1 by Tollef Fog Heen
Import upstream version 1.2.7
124
        res = vp;
125
        apr_sleep(thread_info->work_delay_sleep);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
126
127
        /* simulate a 5% chance of the resource being bad */
128
        chance = lgc(chance);
129
        if ( chance < PERCENT95th ) {
130
            rv = apr_reslist_release(rl, res);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
131
            ABTS_INT_EQUAL(thread_info->tc, APR_SUCCESS, rv);
132
        } else {
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
133
            rv = apr_reslist_invalidate(rl, res);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
134
            ABTS_INT_EQUAL(thread_info->tc, APR_SUCCESS, rv);
135
        }
1 by Tollef Fog Heen
Import upstream version 1.2.7
136
    }
137
138
    return APR_SUCCESS;
139
}
140
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
141
static void test_timeout(abts_case *tc, apr_reslist_t *rl)
1 by Tollef Fog Heen
Import upstream version 1.2.7
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
    apr_reslist_timeout_set(rl, 1000);
150
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
151
    /* deplete all possible resources from the resource list
152
     * so that the next call will block until timeout is reached
153
     * (since there are no other threads to make a resource
1 by Tollef Fog Heen
Import upstream version 1.2.7
154
     * available)
155
     */
156
157
    for (i = 0; i < RESLIST_HMAX; i++) {
158
        rv = apr_reslist_acquire(rl, (void**)&resources[i]);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
159
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1 by Tollef Fog Heen
Import upstream version 1.2.7
160
    }
161
162
    /* next call will block until timeout is reached */
163
    rv = apr_reslist_acquire(rl, &vp);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
164
    ABTS_TRUE(tc, APR_STATUS_IS_TIMEUP(rv));
165
1 by Tollef Fog Heen
Import upstream version 1.2.7
166
    res = vp;
167
168
    /* release the resources; otherwise the destroy operation
169
     * will blow
170
     */
171
    for (i = 0; i < RESLIST_HMAX; i++) {
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
172
        rv = apr_reslist_release(rl, resources[i]);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
173
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
174
    }
175
}
176
177
static void test_shrinking(abts_case *tc, apr_reslist_t *rl)
178
{
179
    apr_status_t rv;
180
    my_resource_t *resources[RESLIST_HMAX];
181
    my_resource_t *res;
182
    void *vp;
183
    int i;
184
    int sleep_time = RESLIST_TTL / RESLIST_HMAX;
185
186
    /* deplete all possible resources from the resource list */
187
    for (i = 0; i < RESLIST_HMAX; i++) {
188
        rv = apr_reslist_acquire(rl, (void**)&resources[i]);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
189
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
190
    }
191
192
    /* Free all resources above RESLIST_SMAX - 1 */
193
    for (i = RESLIST_SMAX - 1; i < RESLIST_HMAX; i++) {
194
        rv = apr_reslist_release(rl, resources[i]);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
195
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
196
    }
197
198
    for (i = 0; i < RESLIST_HMAX; i++) {
199
        rv = apr_reslist_acquire(rl, &vp);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
200
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
201
        res = vp;
202
        apr_sleep(sleep_time);
203
        rv = apr_reslist_release(rl, res);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
204
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
205
    }
206
    apr_sleep(sleep_time);
207
208
    /*
209
     * Now free the remaining elements. This should trigger the shrinking of
210
     * the list
211
     */
212
    for (i = 0; i < RESLIST_SMAX - 1; i++) {
213
        rv = apr_reslist_release(rl, resources[i]);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
214
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
215
    }
216
}
217
218
static void test_reslist(abts_case *tc, void *data)
219
{
220
    int i;
221
    apr_status_t rv;
1 by Tollef Fog Heen
Import upstream version 1.2.7
222
    apr_reslist_t *rl;
223
    my_parameters_t *params;
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
224
    apr_thread_pool_t *thrp;
225
    my_thread_info_t thread_info[CONSUMER_THREADS];
1 by Tollef Fog Heen
Import upstream version 1.2.7
226
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
227
    rv = apr_thread_pool_create(&thrp, CONSUMER_THREADS/2, CONSUMER_THREADS, p);
228
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1 by Tollef Fog Heen
Import upstream version 1.2.7
229
230
    /* Create some parameters that will be passed into each
231
     * constructor and destructor call. */
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
232
    params = apr_pcalloc(p, sizeof(*params));
1 by Tollef Fog Heen
Import upstream version 1.2.7
233
    params->sleep_upon_construct = CONSTRUCT_SLEEP_TIME;
234
    params->sleep_upon_destruct = DESTRUCT_SLEEP_TIME;
235
236
    /* We're going to want 10 blocks of data from our target rmm. */
237
    rv = apr_reslist_create(&rl, RESLIST_MIN, RESLIST_SMAX, RESLIST_HMAX,
238
                            RESLIST_TTL, my_constructor, my_destructor,
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
239
                            params, p);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
240
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
241
242
    for (i = 0; i < CONSUMER_THREADS; i++) {
243
        thread_info[i].tid = i;
244
        thread_info[i].tc = tc;
245
        thread_info[i].reslist = rl;
246
        thread_info[i].work_delay_sleep = WORK_DELAY_SLEEP_TIME;
247
        rv = apr_thread_pool_push(thrp, resource_consuming_thread,
248
                                  &thread_info[i], 0, NULL);
249
        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
250
    }
251
252
    rv = apr_thread_pool_destroy(thrp);
253
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
254
255
    test_timeout(tc, rl);
256
257
    test_shrinking(tc, rl);
258
    ABTS_INT_EQUAL(tc, RESLIST_SMAX, params->c_count - params->d_count);
259
1 by Tollef Fog Heen
Import upstream version 1.2.7
260
    rv = apr_reslist_destroy(rl);
0.3.1 by Stefan Fritsch
Import upstream version 1.3.2+dfsg
261
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
262
}
263
1 by Tollef Fog Heen
Import upstream version 1.2.7
264
#endif /* APR_HAS_THREADS */
1.1.2 by Stefan Fritsch
Import upstream version 1.2.12+dfsg
265
266
abts_suite *testreslist(abts_suite *suite)
267
{
268
    suite = ADD_SUITE(suite);
269
270
#if APR_HAS_THREADS
271
    abts_run_test(suite, test_reslist, NULL);
272
#endif
273
274
    return suite;
275
}