]> granicus.if.org Git - apache/blob - modules/mem/mod_plainmem.c
add creation type parameter per r771286
[apache] / modules / mem / mod_plainmem.c
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
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 /* Memory handler for a plain memory divided in slot.
18  * This one uses plain memory.
19  */
20
21 #include  "ap_slotmem.h"
22
23 struct ap_slotmem_t {
24     char                 *name;       /* per segment name */
25     void                 *base;       /* data set start */
26     apr_size_t           size;        /* size of each memory slot */
27     unsigned int         num;         /* number of mem slots */
28     apr_pool_t           *gpool;      /* per segment global pool */
29     apr_global_mutex_t   *smutex;     /* mutex */
30     struct ap_slotmem_t  *next;       /* location of next allocated segment */
31 };
32
33
34 /* global pool and list of slotmem we are handling */
35 static struct ap_slotmem_t *globallistmem = NULL;
36 static apr_pool_t *gpool = NULL;
37
38 static apr_status_t slotmem_do(ap_slotmem_t *mem, ap_slotmem_callback_fn_t *func, void *data, apr_pool_t *pool)
39 {
40     unsigned int i;
41     void *ptr;
42
43     if (!mem)
44         return APR_ENOSHMAVAIL;
45
46     ptr = mem->base;
47     for (i = 0; i < mem->num; i++) {
48         ptr = ptr + mem->size;
49         func((void *) ptr, data, pool);
50     }
51     return APR_SUCCESS;
52 }
53
54 static apr_status_t slotmem_create(ap_slotmem_t **new, const char *name, apr_size_t item_size, unsigned int item_num, int type, apr_pool_t *pool)
55 {
56     ap_slotmem_t *res;
57     ap_slotmem_t *next = globallistmem;
58     const char *fname;
59
60     if (name) {
61         if (name[0] == ':')
62             fname = name;
63         else
64             fname = ap_server_root_relative(pool, name);
65
66         /* first try to attach to existing slotmem */
67         if (next) {
68             for (;;) {
69                 if (strcmp(next->name, fname) == 0) {
70                     /* we already have it */
71                     *new = next;
72                     return APR_SUCCESS;
73                 }
74                 if (!next->next)
75                     break;
76                 next = next->next;
77             }
78         }
79     }
80     else
81         fname = "anonymous";
82
83     /* create the memory using the gpool */
84     res = (ap_slotmem_t *) apr_pcalloc(gpool, sizeof(ap_slotmem_t));
85     res->base = apr_pcalloc(gpool, item_size * item_num);
86     if (!res->base)
87         return APR_ENOSHMAVAIL;
88
89     /* For the chained slotmem stuff */
90     res->name = apr_pstrdup(gpool, fname);
91     res->size = item_size;
92     res->num = item_num;
93     res->next = NULL;
94     if (globallistmem == NULL)
95         globallistmem = res;
96     else
97         next->next = res;
98
99     *new = res;
100     return APR_SUCCESS;
101 }
102
103 static apr_status_t slotmem_attach(ap_slotmem_t **new, const char *name, apr_size_t *item_size, unsigned int *item_num, apr_pool_t *pool)
104 {
105     ap_slotmem_t *next = globallistmem;
106     const char *fname;
107
108     if (name) {
109         if (name[0] == ':')
110             fname = name;
111         else
112             fname = ap_server_root_relative(pool, name);
113     }
114     else
115         return APR_ENOSHMAVAIL;
116
117     /* first try to attach to existing slotmem */
118     if (next) {
119         for (;;) {
120             if (strcmp(next->name, fname) == 0) {
121                 /* we already have it */
122                 *new = next;
123                 *item_size = next->size;
124                 *item_num = next->num;
125                 return APR_SUCCESS;
126             }
127             if (!next->next)
128                 break;
129             next = next->next;
130         }
131     }
132
133     return APR_ENOSHMAVAIL;
134 }
135
136 static apr_status_t slotmem_mem(ap_slotmem_t *score, unsigned int id, void **mem)
137 {
138
139     void *ptr;
140
141     if (!score)
142         return APR_ENOSHMAVAIL;
143     if (id < 0 || id > score->num)
144         return APR_ENOSHMAVAIL;
145
146     ptr = score->base + score->size * id;
147     if (!ptr)
148         return APR_ENOSHMAVAIL;
149     *mem = ptr;
150     return APR_SUCCESS;
151 }
152
153 static apr_status_t slotmem_get(ap_slotmem_t *slot, unsigned int id, unsigned char *dest, apr_size_t dest_len)
154 {
155
156     void *ptr;
157     apr_status_t ret;
158
159     ret = slotmem_mem(slot, id, &ptr);
160     if (ret != APR_SUCCESS) {
161         return ret;
162     }
163     memcpy(dest, ptr, dest_len); /* bounds check? */
164     return APR_SUCCESS;
165 }
166
167 static apr_status_t slotmem_put(ap_slotmem_t *slot, unsigned int id, unsigned char *src, apr_size_t src_len)
168 {
169
170     void *ptr;
171     apr_status_t ret;
172
173     ret = slotmem_mem(slot, id, &ptr);
174     if (ret != APR_SUCCESS) {
175         return ret;
176     }
177     memcpy(ptr, src, src_len); /* bounds check? */
178     return APR_SUCCESS;
179 }
180
181 static const ap_slotmem_storage_method storage = {
182     "plainmem",
183     &slotmem_do,
184     &slotmem_create,
185     &slotmem_attach,
186     &slotmem_mem,
187     &slotmem_get,
188     &slotmem_put
189 };
190
191 static int pre_config(apr_pool_t *p, apr_pool_t *plog,
192                       apr_pool_t *ptemp)
193 {
194     gpool = p;
195     return OK;
196 }
197
198 static void ap_plainmem_register_hook(apr_pool_t *p)
199 {
200     /* XXX: static const char * const prePos[] = { "mod_slotmem.c", NULL }; */
201     ap_register_provider(p, AP_SLOTMEM_STORAGE, "plain", "0", &storage);
202     ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE);
203 }
204
205 module AP_MODULE_DECLARE_DATA plainmem_module = {
206     STANDARD20_MODULE_STUFF,
207     NULL,                        /* create per-directory config structure */
208     NULL,                        /* merge per-directory config structures */
209     NULL,                        /* create per-server config structure */
210     NULL,                        /* merge per-server config structures */
211     NULL,                        /* command apr_table_t */
212     ap_plainmem_register_hook    /* register hooks */
213 };
214