Lines 25-35
Link Here
|
25 |
|
25 |
|
26 |
#include "httpd.h" |
26 |
#include "httpd.h" |
27 |
#include "http_main.h" |
27 |
#include "http_main.h" |
28 |
#include "ap_mpm.h" /* for ap_mpm_query() */ |
28 |
#include "http_core.h" |
29 |
|
29 |
|
30 |
#define AP_SLOTMEM_IS_PREGRAB(t) (t->desc.type & AP_SLOTMEM_TYPE_PREGRAB) |
30 |
#define AP_SLOTMEM_IS_PREGRAB(t) (t->desc->type & AP_SLOTMEM_TYPE_PREGRAB) |
31 |
#define AP_SLOTMEM_IS_PERSIST(t) (t->desc.type & AP_SLOTMEM_TYPE_PERSIST) |
31 |
#define AP_SLOTMEM_IS_PERSIST(t) (t->desc->type & AP_SLOTMEM_TYPE_PERSIST) |
32 |
#define AP_SLOTMEM_IS_CLEARINUSE(t) (t->desc.type & AP_SLOTMEM_TYPE_CLEARINUSE) |
32 |
#define AP_SLOTMEM_IS_CLEARINUSE(t) (t->desc->type & AP_SLOTMEM_TYPE_CLEARINUSE) |
33 |
|
33 |
|
34 |
/* The description of the slots to reuse the slotmem */ |
34 |
/* The description of the slots to reuse the slotmem */ |
35 |
typedef struct { |
35 |
typedef struct { |
Lines 47-57
struct ap_slotmem_instance_t {
Link Here
|
47 |
int fbased; /* filebased? */ |
47 |
int fbased; /* filebased? */ |
48 |
void *shm; /* ptr to memory segment (apr_shm_t *) */ |
48 |
void *shm; /* ptr to memory segment (apr_shm_t *) */ |
49 |
void *base; /* data set start */ |
49 |
void *base; /* data set start */ |
50 |
apr_pool_t *gpool; /* per segment global pool */ |
50 |
apr_pool_t *pool; /* per segment pool (generation cleared) */ |
51 |
char *inuse; /* in-use flag table*/ |
51 |
char *inuse; /* in-use flag table*/ |
52 |
unsigned int *num_free; /* slot free count for this instance */ |
52 |
unsigned int *num_free; /* slot free count for this instance */ |
53 |
void *persist; /* persist dataset start */ |
53 |
void *persist; /* persist dataset start */ |
54 |
sharedslotdesc_t desc; /* per slot desc */ |
54 |
const sharedslotdesc_t *desc; /* per slot desc */ |
55 |
struct ap_slotmem_instance_t *next; /* location of next allocated segment */ |
55 |
struct ap_slotmem_instance_t *next; /* location of next allocated segment */ |
56 |
}; |
56 |
}; |
57 |
|
57 |
|
Lines 64-70
struct ap_slotmem_instance_t {
Link Here
|
64 |
*/ |
64 |
*/ |
65 |
|
65 |
|
66 |
/* global pool and list of slotmem we are handling */ |
66 |
/* global pool and list of slotmem we are handling */ |
67 |
static struct ap_slotmem_instance_t *globallistmem = NULL; |
67 |
static struct ap_slotmem_instance_t *globallistmem = NULL, |
|
|
68 |
**retained_globallistmem = NULL; |
68 |
static apr_pool_t *gpool = NULL; |
69 |
static apr_pool_t *gpool = NULL; |
69 |
|
70 |
|
70 |
#define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-" |
71 |
#define DEFAULT_SLOTMEM_PREFIX "slotmem-shm-" |
Lines 71-101
static apr_pool_t *gpool = NULL;
Link Here
|
71 |
#define DEFAULT_SLOTMEM_SUFFIX ".shm" |
72 |
#define DEFAULT_SLOTMEM_SUFFIX ".shm" |
72 |
#define DEFAULT_SLOTMEM_PERSIST_SUFFIX ".persist" |
73 |
#define DEFAULT_SLOTMEM_PERSIST_SUFFIX ".persist" |
73 |
|
74 |
|
74 |
/* Unixes (and Netware) have the unlink() semantic, which allows to |
|
|
75 |
* apr_file_remove() a file still in use (opened elsewhere), the inode |
76 |
* remains until the last fd is closed, whereas any file created with |
77 |
* the same name/path will use a new inode. |
78 |
* |
79 |
* On windows and OS/2 ("\SHAREMEM\..." tree), apr_file_remove() marks |
80 |
* the files for deletion until the last HANDLE is closed, meanwhile the |
81 |
* same file/path can't be opened/recreated. |
82 |
* Thus on graceful restart (the only restart mode with mpm_winnt), the |
83 |
* old file may still exist until all the children stop, while we ought |
84 |
* to create a new one for our new clear SHM. Therefore, we would only |
85 |
* be able to reuse (attach) the old SHM, preventing some changes to |
86 |
* the config file, like the number of balancers/members, since the |
87 |
* size checks (to fit the new config) would fail. Let's avoid this by |
88 |
* including the generation number in the SHM filename (obviously not |
89 |
* the persisted name!) |
90 |
*/ |
91 |
#ifndef SLOTMEM_UNLINK_SEMANTIC |
92 |
#if defined(WIN32) || defined(OS2) |
93 |
#define SLOTMEM_UNLINK_SEMANTIC 0 |
94 |
#else |
95 |
#define SLOTMEM_UNLINK_SEMANTIC 1 |
96 |
#endif |
97 |
#endif |
98 |
|
99 |
/* |
75 |
/* |
100 |
* Persist the slotmem in a file |
76 |
* Persist the slotmem in a file |
101 |
* slotmem name and file name. |
77 |
* slotmem name and file name. |
Lines 113-130
static int slotmem_filenames(apr_pool_t *pool,
Link Here
|
113 |
|
89 |
|
114 |
if (slotname && *slotname && strcasecmp(slotname, "none") != 0) { |
90 |
if (slotname && *slotname && strcasecmp(slotname, "none") != 0) { |
115 |
if (slotname[0] != '/') { |
91 |
if (slotname[0] != '/') { |
116 |
#if !SLOTMEM_UNLINK_SEMANTIC |
|
|
117 |
/* Each generation needs its own file name. */ |
118 |
int generation = 0; |
119 |
ap_mpm_query(AP_MPMQ_GENERATION, &generation); |
120 |
fname = apr_psprintf(pool, "%s%s_%x%s", DEFAULT_SLOTMEM_PREFIX, |
121 |
slotname, generation, DEFAULT_SLOTMEM_SUFFIX); |
122 |
#else |
123 |
/* Reuse the same file name for each generation. */ |
124 |
fname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX, |
92 |
fname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX, |
125 |
slotname, DEFAULT_SLOTMEM_SUFFIX, |
93 |
slotname, DEFAULT_SLOTMEM_SUFFIX, |
126 |
NULL); |
94 |
NULL); |
127 |
#endif |
|
|
128 |
fname = ap_runtime_dir_relative(pool, fname); |
95 |
fname = ap_runtime_dir_relative(pool, fname); |
129 |
} |
96 |
} |
130 |
else { |
97 |
else { |
Lines 135-151
static int slotmem_filenames(apr_pool_t *pool,
Link Here
|
135 |
} |
102 |
} |
136 |
|
103 |
|
137 |
if (persistname) { |
104 |
if (persistname) { |
138 |
/* Persisted file names are immutable... */ |
|
|
139 |
#if !SLOTMEM_UNLINK_SEMANTIC |
140 |
if (slotname[0] != '/') { |
141 |
pname = apr_pstrcat(pool, DEFAULT_SLOTMEM_PREFIX, |
142 |
slotname, DEFAULT_SLOTMEM_SUFFIX, |
143 |
DEFAULT_SLOTMEM_PERSIST_SUFFIX, |
144 |
NULL); |
145 |
pname = ap_runtime_dir_relative(pool, pname); |
146 |
} |
147 |
else |
148 |
#endif |
149 |
pname = apr_pstrcat(pool, fname, |
105 |
pname = apr_pstrcat(pool, fname, |
150 |
DEFAULT_SLOTMEM_PERSIST_SUFFIX, |
106 |
DEFAULT_SLOTMEM_PERSIST_SUFFIX, |
151 |
NULL); |
107 |
NULL); |
Lines 170-176
static void slotmem_clearinuse(ap_slotmem_instance
Link Here
|
170 |
|
126 |
|
171 |
inuse = slot->inuse; |
127 |
inuse = slot->inuse; |
172 |
|
128 |
|
173 |
for (i = 0; i < slot->desc.num; i++, inuse++) { |
129 |
for (i = 0; i < slot->desc->num; i++, inuse++) { |
174 |
if (*inuse) { |
130 |
if (*inuse) { |
175 |
*inuse = 0; |
131 |
*inuse = 0; |
176 |
(*slot->num_free)++; |
132 |
(*slot->num_free)++; |
Lines 191-201
static void store_slotmem(ap_slotmem_instance_t *s
Link Here
|
191 |
|
147 |
|
192 |
if (storename) { |
148 |
if (storename) { |
193 |
rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, |
149 |
rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, |
194 |
APR_OS_DEFAULT, slotmem->gpool); |
150 |
APR_OS_DEFAULT, slotmem->pool); |
195 |
if (APR_STATUS_IS_EEXIST(rv)) { |
151 |
if (APR_STATUS_IS_EEXIST(rv)) { |
196 |
apr_file_remove(storename, slotmem->gpool); |
152 |
apr_file_remove(storename, slotmem->pool); |
197 |
rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, |
153 |
rv = apr_file_open(&fp, storename, APR_CREATE | APR_READ | APR_WRITE, |
198 |
APR_OS_DEFAULT, slotmem->gpool); |
154 |
APR_OS_DEFAULT, slotmem->pool); |
199 |
} |
155 |
} |
200 |
if (rv != APR_SUCCESS) { |
156 |
if (rv != APR_SUCCESS) { |
201 |
return; |
157 |
return; |
Lines 203-230
static void store_slotmem(ap_slotmem_instance_t *s
Link Here
|
203 |
if (AP_SLOTMEM_IS_CLEARINUSE(slotmem)) { |
159 |
if (AP_SLOTMEM_IS_CLEARINUSE(slotmem)) { |
204 |
slotmem_clearinuse(slotmem); |
160 |
slotmem_clearinuse(slotmem); |
205 |
} |
161 |
} |
206 |
nbytes = (slotmem->desc.size * slotmem->desc.num) + |
162 |
nbytes = (slotmem->desc->size * slotmem->desc->num) + |
207 |
(slotmem->desc.num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET; |
163 |
(slotmem->desc->num * sizeof(char)) + AP_UNSIGNEDINT_OFFSET; |
208 |
apr_md5(digest, slotmem->persist, nbytes); |
164 |
apr_md5(digest, slotmem->persist, nbytes); |
209 |
rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL); |
165 |
rv = apr_file_write_full(fp, slotmem->persist, nbytes, NULL); |
210 |
if (rv == APR_SUCCESS) { |
166 |
if (rv == APR_SUCCESS) { |
211 |
rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL); |
167 |
rv = apr_file_write_full(fp, digest, APR_MD5_DIGESTSIZE, NULL); |
212 |
} |
168 |
} |
|
|
169 |
if (rv == APR_SUCCESS) { |
170 |
rv = apr_file_write_full(fp, slotmem->desc, AP_SLOTMEM_OFFSET, |
171 |
NULL); |
172 |
} |
213 |
apr_file_close(fp); |
173 |
apr_file_close(fp); |
214 |
if (rv != APR_SUCCESS) { |
174 |
if (rv != APR_SUCCESS) { |
215 |
apr_file_remove(storename, slotmem->gpool); |
175 |
apr_file_remove(storename, slotmem->pool); |
216 |
} |
176 |
} |
217 |
} |
177 |
} |
218 |
} |
178 |
} |
219 |
|
179 |
|
220 |
static apr_status_t restore_slotmem(void *ptr, const char *storename, |
180 |
static apr_status_t restore_slotmem(sharedslotdesc_t *desc, |
221 |
apr_size_t size, apr_pool_t *pool) |
181 |
const char *storename, apr_size_t size, |
|
|
182 |
apr_pool_t *pool) |
222 |
{ |
183 |
{ |
223 |
apr_file_t *fp; |
184 |
apr_file_t *fp; |
224 |
apr_size_t nbytes = size; |
185 |
apr_status_t rv = APR_ENOTIMPL; |
225 |
apr_status_t rv = APR_SUCCESS; |
|
|
226 |
unsigned char digest[APR_MD5_DIGESTSIZE]; |
186 |
unsigned char digest[APR_MD5_DIGESTSIZE]; |
227 |
unsigned char digest2[APR_MD5_DIGESTSIZE]; |
187 |
unsigned char digest2[APR_MD5_DIGESTSIZE]; |
|
|
188 |
char aligned_desc[AP_SLOTMEM_OFFSET]; |
189 |
void *ptr = (char *)desc + AP_SLOTMEM_OFFSET; |
190 |
apr_size_t dsize = size - AP_SLOTMEM_OFFSET; |
191 |
apr_size_t nbytes = dsize; |
228 |
|
192 |
|
229 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335) |
193 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335) |
230 |
"restoring %s", storename); |
194 |
"restoring %s", storename); |
Lines 234-240
static void store_slotmem(ap_slotmem_instance_t *s
Link Here
|
234 |
pool); |
198 |
pool); |
235 |
if (rv == APR_SUCCESS) { |
199 |
if (rv == APR_SUCCESS) { |
236 |
rv = apr_file_read(fp, ptr, &nbytes); |
200 |
rv = apr_file_read(fp, ptr, &nbytes); |
237 |
if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == size) { |
201 |
if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == dsize) { |
238 |
rv = APR_SUCCESS; /* for successful return @ EOF */ |
202 |
rv = APR_SUCCESS; /* for successful return @ EOF */ |
239 |
/* |
203 |
/* |
240 |
* if at EOF, don't bother checking md5 |
204 |
* if at EOF, don't bother checking md5 |
Lines 243-270
static void store_slotmem(ap_slotmem_instance_t *s
Link Here
|
243 |
if (apr_file_eof(fp) != APR_EOF) { |
207 |
if (apr_file_eof(fp) != APR_EOF) { |
244 |
apr_size_t ds = APR_MD5_DIGESTSIZE; |
208 |
apr_size_t ds = APR_MD5_DIGESTSIZE; |
245 |
rv = apr_file_read(fp, digest, &ds); |
209 |
rv = apr_file_read(fp, digest, &ds); |
246 |
if ((rv == APR_SUCCESS || rv == APR_EOF) && |
210 |
if ((rv == APR_SUCCESS || rv == APR_EOF) |
247 |
ds == APR_MD5_DIGESTSIZE) { |
211 |
&& ds == APR_MD5_DIGESTSIZE) { |
248 |
rv = APR_SUCCESS; |
|
|
249 |
apr_md5(digest2, ptr, nbytes); |
212 |
apr_md5(digest2, ptr, nbytes); |
250 |
if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) { |
213 |
if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) { |
251 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, |
214 |
rv = APR_EMISMATCH; |
252 |
APLOGNO(02551) "bad md5 match"); |
|
|
253 |
rv = APR_EGENERAL; |
254 |
} |
215 |
} |
|
|
216 |
/* |
217 |
* if at EOF, don't bother checking desc |
218 |
* - backwards compatibility |
219 |
* */ |
220 |
else if (apr_file_eof(fp) != APR_EOF) { |
221 |
nbytes = sizeof(aligned_desc); |
222 |
rv = apr_file_read(fp, aligned_desc, &nbytes); |
223 |
if ((rv == APR_SUCCESS || rv == APR_EOF) |
224 |
&& nbytes == sizeof(aligned_desc)) { |
225 |
if (memcmp(desc, aligned_desc, |
226 |
sizeof(aligned_desc))) { |
227 |
rv = APR_EMISMATCH; |
228 |
} |
229 |
else { |
230 |
rv = APR_SUCCESS; |
231 |
} |
232 |
} |
233 |
else if (rv == APR_SUCCESS || rv == APR_EOF) { |
234 |
rv = APR_INCOMPLETE; |
235 |
} |
236 |
} |
237 |
else { |
238 |
rv = APR_EOF; |
239 |
} |
255 |
} |
240 |
} |
|
|
241 |
else if (rv == APR_SUCCESS || rv == APR_EOF) { |
242 |
rv = APR_INCOMPLETE; |
243 |
} |
256 |
} |
244 |
} |
257 |
else { |
245 |
else { |
258 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, |
246 |
rv = APR_EOF; |
259 |
APLOGNO(02552) "at EOF... bypassing md5 match check (old persist file?)"); |
|
|
260 |
} |
247 |
} |
|
|
248 |
if (rv == APR_EMISMATCH) { |
249 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02551) |
250 |
"persisted slotmem md5/desc mismatch"); |
251 |
} |
252 |
else if (rv == APR_EOF) { |
253 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(02552) |
254 |
"persisted slotmem at EOF... bypassing md5/desc match check " |
255 |
"(old persist file?)"); |
256 |
rv = APR_SUCCESS; |
257 |
} |
261 |
} |
258 |
} |
262 |
else if (nbytes != size) { |
259 |
else if (rv == APR_SUCCESS || rv == APR_EOF) { |
263 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, |
260 |
rv = APR_INCOMPLETE; |
264 |
APLOGNO(02553) "Expected %" APR_SIZE_T_FMT ": Read %" APR_SIZE_T_FMT, |
|
|
265 |
size, nbytes); |
266 |
rv = APR_EGENERAL; |
267 |
} |
261 |
} |
|
|
262 |
if (rv == APR_INCOMPLETE) { |
263 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02553) |
264 |
"persisted slotmem read had unexpected size"); |
265 |
} |
268 |
apr_file_close(fp); |
266 |
apr_file_close(fp); |
269 |
} |
267 |
} |
270 |
} |
268 |
} |
Lines 271-296
static void store_slotmem(ap_slotmem_instance_t *s
Link Here
|
271 |
return rv; |
269 |
return rv; |
272 |
} |
270 |
} |
273 |
|
271 |
|
274 |
static apr_status_t cleanup_slotmem(void *param) |
272 |
static apr_status_t cleanup_slotmem(void *is_startup) |
275 |
{ |
273 |
{ |
276 |
ap_slotmem_instance_t **mem = param; |
274 |
int is_exiting = (ap_state_query(AP_SQ_MAIN_STATE) == AP_SQ_MS_EXITING); |
|
|
275 |
ap_slotmem_instance_t *mem; |
277 |
|
276 |
|
278 |
if (*mem) { |
277 |
/* When in startup/pre-config's cleanup, the retained data and global pool |
279 |
ap_slotmem_instance_t *next = *mem; |
278 |
* are not used yet, but the SHMs contents were untouched hence they don't |
280 |
while (next) { |
279 |
* need to be persisted, simply unlink them. |
281 |
if (AP_SLOTMEM_IS_PERSIST(next)) { |
280 |
* Otherwise when restarting or stopping we want to flush persisted data, |
282 |
store_slotmem(next); |
281 |
* and in the stopping/exiting case we also want to unlink the SHMs. |
|
|
282 |
*/ |
283 |
for (mem = globallistmem; mem; mem = mem->next) { |
284 |
int unlink; |
285 |
if (is_startup) { |
286 |
unlink = mem->fbased; |
287 |
} |
288 |
else { |
289 |
if (AP_SLOTMEM_IS_PERSIST(mem)) { |
290 |
store_slotmem(mem); |
283 |
} |
291 |
} |
284 |
apr_shm_destroy((apr_shm_t *)next->shm); |
292 |
unlink = is_exiting; |
285 |
if (next->fbased) { |
|
|
286 |
apr_shm_remove(next->name, next->gpool); |
287 |
apr_file_remove(next->name, next->gpool); |
288 |
} |
289 |
next = next->next; |
290 |
} |
293 |
} |
|
|
294 |
if (unlink) { |
295 |
/* Some systems may require the descriptor to be closed before |
296 |
* unlink, thus call destroy() first (this won't free mem->shm |
297 |
* so it's safe to call delete() afterward). |
298 |
*/ |
299 |
apr_shm_destroy(mem->shm); |
300 |
apr_shm_delete(mem->shm); |
301 |
} |
291 |
} |
302 |
} |
292 |
/* apr_pool_destroy(gpool); */ |
303 |
|
|
|
304 |
if (is_exiting) { |
305 |
*retained_globallistmem = NULL; |
306 |
} |
307 |
else if (!is_startup) { |
308 |
*retained_globallistmem = globallistmem; |
309 |
} |
293 |
globallistmem = NULL; |
310 |
globallistmem = NULL; |
|
|
311 |
|
294 |
return APR_SUCCESS; |
312 |
return APR_SUCCESS; |
295 |
} |
313 |
} |
296 |
|
314 |
|
Lines 309-315
static apr_status_t slotmem_doall(ap_slotmem_insta
Link Here
|
309 |
|
327 |
|
310 |
ptr = (char *)mem->base; |
328 |
ptr = (char *)mem->base; |
311 |
inuse = mem->inuse; |
329 |
inuse = mem->inuse; |
312 |
for (i = 0; i < mem->desc.num; i++, inuse++) { |
330 |
for (i = 0; i < mem->desc->num; i++, inuse++) { |
313 |
if (!AP_SLOTMEM_IS_PREGRAB(mem) || |
331 |
if (!AP_SLOTMEM_IS_PREGRAB(mem) || |
314 |
(AP_SLOTMEM_IS_PREGRAB(mem) && *inuse)) { |
332 |
(AP_SLOTMEM_IS_PREGRAB(mem) && *inuse)) { |
315 |
retval = func((void *) ptr, data, pool); |
333 |
retval = func((void *) ptr, data, pool); |
Lines 316-322
static apr_status_t slotmem_doall(ap_slotmem_insta
Link Here
|
316 |
if (retval != APR_SUCCESS) |
334 |
if (retval != APR_SUCCESS) |
317 |
break; |
335 |
break; |
318 |
} |
336 |
} |
319 |
ptr += mem->desc.size; |
337 |
ptr += mem->desc->size; |
320 |
} |
338 |
} |
321 |
return retval; |
339 |
return retval; |
322 |
} |
340 |
} |
Lines 329-335
static apr_status_t slotmem_create(ap_slotmem_inst
Link Here
|
329 |
int fbased = 1; |
347 |
int fbased = 1; |
330 |
int restored = 0; |
348 |
int restored = 0; |
331 |
char *ptr; |
349 |
char *ptr; |
332 |
sharedslotdesc_t desc; |
350 |
sharedslotdesc_t *desc; |
333 |
ap_slotmem_instance_t *res; |
351 |
ap_slotmem_instance_t *res; |
334 |
ap_slotmem_instance_t *next = globallistmem; |
352 |
ap_slotmem_instance_t *next = globallistmem; |
335 |
const char *fname, *pname = NULL; |
353 |
const char *fname, *pname = NULL; |
Lines 339-348
static apr_status_t slotmem_create(ap_slotmem_inst
Link Here
|
339 |
(item_num * sizeof(char)) + basesize; |
357 |
(item_num * sizeof(char)) + basesize; |
340 |
int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0; |
358 |
int persist = (type & AP_SLOTMEM_TYPE_PERSIST) != 0; |
341 |
apr_status_t rv; |
359 |
apr_status_t rv; |
|
|
360 |
apr_pool_t *p; |
342 |
|
361 |
|
343 |
if (gpool == NULL) { |
|
|
344 |
return APR_ENOSHMAVAIL; |
345 |
} |
346 |
if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) { |
362 |
if (slotmem_filenames(pool, name, &fname, persist ? &pname : NULL)) { |
347 |
/* first try to attach to existing slotmem */ |
363 |
/* first try to attach to existing slotmem */ |
348 |
if (next) { |
364 |
if (next) { |
Lines 372-414
static apr_status_t slotmem_create(ap_slotmem_inst
Link Here
|
372 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300) |
388 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02300) |
373 |
"create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size, |
389 |
"create %s: %"APR_SIZE_T_FMT"/%u", fname, item_size, |
374 |
item_num); |
390 |
item_num); |
375 |
if (fbased) { |
|
|
376 |
rv = apr_shm_attach(&shm, fname, gpool); |
377 |
} |
378 |
else { |
379 |
rv = APR_EINVAL; |
380 |
} |
381 |
if (rv == APR_SUCCESS) { |
382 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02598) |
383 |
"apr_shm_attach() succeeded"); |
384 |
|
391 |
|
385 |
/* check size */ |
392 |
|
386 |
if (apr_shm_size_get(shm) != size) { |
393 |
{ |
387 |
apr_shm_detach(shm); |
|
|
388 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02599) |
389 |
"existing shared memory for %s could not be used (failed size check)", |
390 |
fname); |
391 |
return APR_EINVAL; |
392 |
} |
393 |
ptr = (char *)apr_shm_baseaddr_get(shm); |
394 |
memcpy(&desc, ptr, sizeof(desc)); |
395 |
if (desc.size != item_size || desc.num != item_num) { |
396 |
apr_shm_detach(shm); |
397 |
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02600) |
398 |
"existing shared memory for %s could not be used (failed contents check)", |
399 |
fname); |
400 |
return APR_EINVAL; |
401 |
} |
402 |
ptr += AP_SLOTMEM_OFFSET; |
403 |
} |
404 |
else { |
405 |
apr_size_t dsize = size - AP_SLOTMEM_OFFSET; |
406 |
if (fbased) { |
394 |
if (fbased) { |
407 |
apr_shm_remove(fname, gpool); |
395 |
apr_shm_remove(fname, pool); |
408 |
rv = apr_shm_create(&shm, size, fname, gpool); |
396 |
rv = apr_shm_create(&shm, size, fname, gpool); |
409 |
} |
397 |
} |
410 |
else { |
398 |
else { |
411 |
rv = apr_shm_create(&shm, size, NULL, gpool); |
399 |
rv = apr_shm_create(&shm, size, NULL, pool); |
412 |
} |
400 |
} |
413 |
ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR, |
401 |
ap_log_error(APLOG_MARK, rv == APR_SUCCESS ? APLOG_DEBUG : APLOG_ERR, |
414 |
rv, ap_server_conf, APLOGNO(02611) |
402 |
rv, ap_server_conf, APLOGNO(02611) |
Lines 418-472
static apr_status_t slotmem_create(ap_slotmem_inst
Link Here
|
418 |
if (rv != APR_SUCCESS) { |
406 |
if (rv != APR_SUCCESS) { |
419 |
return rv; |
407 |
return rv; |
420 |
} |
408 |
} |
421 |
ptr = (char *)apr_shm_baseaddr_get(shm); |
409 |
|
422 |
desc.size = item_size; |
410 |
desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm); |
423 |
desc.num = item_num; |
411 |
memset(desc, 0, size); |
424 |
desc.type = type; |
412 |
desc->size = item_size; |
425 |
memcpy(ptr, &desc, sizeof(desc)); |
413 |
desc->num = item_num; |
426 |
ptr += AP_SLOTMEM_OFFSET; |
414 |
desc->type = type; |
427 |
memset(ptr, 0, dsize); |
415 |
|
428 |
/* |
416 |
/* |
429 |
* TODO: Error check the below... What error makes |
417 |
* TODO: Error check the below... What error makes |
430 |
* sense if the restore fails? Any? |
418 |
* sense if the restore fails? Any? |
|
|
419 |
* For now, we continue with a fresh new slotmem, |
420 |
* but NOTICE in the log. |
431 |
*/ |
421 |
*/ |
432 |
if (persist) { |
422 |
if (persist) { |
433 |
rv = restore_slotmem(ptr, pname, dsize, pool); |
423 |
rv = restore_slotmem(desc, pname, size, pool); |
434 |
if (rv == APR_SUCCESS) { |
424 |
if (rv == APR_SUCCESS) { |
435 |
restored = 1; |
425 |
restored = 1; |
436 |
} |
426 |
} |
437 |
else { |
427 |
else { |
438 |
/* just in case, re-zero */ |
428 |
/* just in case, re-zero */ |
439 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
429 |
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, |
440 |
APLOGNO(02554) "could not restore %s", fname); |
430 |
APLOGNO(02554) "could not restore %s", fname); |
441 |
memset(ptr, 0, dsize); |
431 |
memset((char *)desc + AP_SLOTMEM_OFFSET, 0, |
|
|
432 |
size - AP_SLOTMEM_OFFSET); |
442 |
} |
433 |
} |
443 |
} |
434 |
} |
444 |
} |
435 |
} |
445 |
|
436 |
|
|
|
437 |
p = fbased ? gpool : pool; |
438 |
ptr = (char *)desc + AP_SLOTMEM_OFFSET; |
439 |
|
446 |
/* For the chained slotmem stuff */ |
440 |
/* For the chained slotmem stuff */ |
447 |
res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, |
441 |
res = apr_pcalloc(p, sizeof(ap_slotmem_instance_t)); |
448 |
sizeof(ap_slotmem_instance_t)); |
442 |
res->name = apr_pstrdup(p, fname); |
449 |
res->name = apr_pstrdup(gpool, fname); |
443 |
res->pname = apr_pstrdup(p, pname); |
450 |
res->pname = apr_pstrdup(gpool, pname); |
|
|
451 |
res->fbased = fbased; |
444 |
res->fbased = fbased; |
452 |
res->shm = shm; |
445 |
res->shm = shm; |
|
|
446 |
res->persist = (void *)ptr; |
453 |
res->num_free = (unsigned int *)ptr; |
447 |
res->num_free = (unsigned int *)ptr; |
|
|
448 |
ptr += AP_UNSIGNEDINT_OFFSET; |
454 |
if (!restored) { |
449 |
if (!restored) { |
455 |
*res->num_free = item_num; |
450 |
*res->num_free = item_num; |
456 |
} |
451 |
} |
457 |
res->persist = (void *)ptr; |
|
|
458 |
ptr += AP_UNSIGNEDINT_OFFSET; |
459 |
res->base = (void *)ptr; |
452 |
res->base = (void *)ptr; |
460 |
res->desc = desc; |
453 |
res->desc = desc; |
461 |
res->gpool = gpool; |
454 |
res->pool = pool; |
462 |
res->next = NULL; |
455 |
res->next = NULL; |
463 |
res->inuse = ptr + basesize; |
456 |
res->inuse = ptr + basesize; |
464 |
if (globallistmem == NULL) { |
457 |
if (fbased) { |
465 |
globallistmem = res; |
458 |
if (globallistmem == NULL) { |
|
|
459 |
globallistmem = res; |
460 |
} |
461 |
else { |
462 |
next->next = res; |
463 |
} |
466 |
} |
464 |
} |
467 |
else { |
|
|
468 |
next->next = res; |
469 |
} |
470 |
|
465 |
|
471 |
*new = res; |
466 |
*new = res; |
472 |
return APR_SUCCESS; |
467 |
return APR_SUCCESS; |
Lines 480-493
static apr_status_t slotmem_attach(ap_slotmem_inst
Link Here
|
480 |
char *ptr; |
475 |
char *ptr; |
481 |
ap_slotmem_instance_t *res; |
476 |
ap_slotmem_instance_t *res; |
482 |
ap_slotmem_instance_t *next = globallistmem; |
477 |
ap_slotmem_instance_t *next = globallistmem; |
483 |
sharedslotdesc_t desc; |
478 |
sharedslotdesc_t *desc; |
484 |
const char *fname; |
479 |
const char *fname; |
485 |
apr_shm_t *shm; |
480 |
apr_shm_t *shm; |
486 |
apr_status_t rv; |
481 |
apr_status_t rv; |
487 |
|
482 |
|
488 |
if (gpool == NULL) { |
|
|
489 |
return APR_ENOSHMAVAIL; |
490 |
} |
491 |
if (!slotmem_filenames(pool, name, &fname, NULL)) { |
483 |
if (!slotmem_filenames(pool, name, &fname, NULL)) { |
492 |
return APR_ENOSHMAVAIL; |
484 |
return APR_ENOSHMAVAIL; |
493 |
} |
485 |
} |
Lines 501-508
static apr_status_t slotmem_attach(ap_slotmem_inst
Link Here
|
501 |
if (strcmp(next->name, fname) == 0) { |
493 |
if (strcmp(next->name, fname) == 0) { |
502 |
/* we already have it */ |
494 |
/* we already have it */ |
503 |
*new = next; |
495 |
*new = next; |
504 |
*item_size = next->desc.size; |
496 |
*item_size = next->desc->size; |
505 |
*item_num = next->desc.num; |
497 |
*item_num = next->desc->num; |
506 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
498 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
507 |
APLOGNO(02302) |
499 |
APLOGNO(02302) |
508 |
"attach found %s: %"APR_SIZE_T_FMT"/%u", fname, |
500 |
"attach found %s: %"APR_SIZE_T_FMT"/%u", fname, |
Lines 523-545
static apr_status_t slotmem_attach(ap_slotmem_inst
Link Here
|
523 |
} |
515 |
} |
524 |
|
516 |
|
525 |
/* Read the description of the slotmem */ |
517 |
/* Read the description of the slotmem */ |
526 |
ptr = (char *)apr_shm_baseaddr_get(shm); |
518 |
desc = (sharedslotdesc_t *)apr_shm_baseaddr_get(shm); |
527 |
memcpy(&desc, ptr, sizeof(desc)); |
519 |
ptr = (char *)desc + AP_SLOTMEM_OFFSET; |
528 |
ptr += AP_SLOTMEM_OFFSET; |
|
|
529 |
|
520 |
|
530 |
/* For the chained slotmem stuff */ |
521 |
/* For the chained slotmem stuff */ |
531 |
res = (ap_slotmem_instance_t *) apr_pcalloc(gpool, |
522 |
res = apr_pcalloc(gpool, sizeof(ap_slotmem_instance_t)); |
532 |
sizeof(ap_slotmem_instance_t)); |
|
|
533 |
res->name = apr_pstrdup(gpool, fname); |
523 |
res->name = apr_pstrdup(gpool, fname); |
534 |
res->fbased = 1; |
524 |
res->fbased = 1; |
535 |
res->shm = shm; |
525 |
res->shm = shm; |
|
|
526 |
res->persist = (void *)ptr; |
536 |
res->num_free = (unsigned int *)ptr; |
527 |
res->num_free = (unsigned int *)ptr; |
537 |
res->persist = (void *)ptr; |
|
|
538 |
ptr += AP_UNSIGNEDINT_OFFSET; |
528 |
ptr += AP_UNSIGNEDINT_OFFSET; |
539 |
res->base = (void *)ptr; |
529 |
res->base = (void *)ptr; |
540 |
res->desc = desc; |
530 |
res->desc = desc; |
541 |
res->gpool = gpool; |
531 |
res->pool = pool; |
542 |
res->inuse = ptr + (desc.size * desc.num); |
532 |
res->inuse = ptr + (desc->size * desc->num); |
543 |
res->next = NULL; |
533 |
res->next = NULL; |
544 |
if (globallistmem == NULL) { |
534 |
if (globallistmem == NULL) { |
545 |
globallistmem = res; |
535 |
globallistmem = res; |
Lines 549-556
static apr_status_t slotmem_attach(ap_slotmem_inst
Link Here
|
549 |
} |
539 |
} |
550 |
|
540 |
|
551 |
*new = res; |
541 |
*new = res; |
552 |
*item_size = desc.size; |
542 |
*item_size = desc->size; |
553 |
*item_num = desc.num; |
543 |
*item_num = desc->num; |
554 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
544 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
555 |
APLOGNO(02303) |
545 |
APLOGNO(02303) |
556 |
"attach found %s: %"APR_SIZE_T_FMT"/%u", fname, |
546 |
"attach found %s: %"APR_SIZE_T_FMT"/%u", fname, |
Lines 566-576
static apr_status_t slotmem_dptr(ap_slotmem_instan
Link Here
|
566 |
if (!slot) { |
556 |
if (!slot) { |
567 |
return APR_ENOSHMAVAIL; |
557 |
return APR_ENOSHMAVAIL; |
568 |
} |
558 |
} |
569 |
if (id >= slot->desc.num) { |
559 |
if (id >= slot->desc->num) { |
570 |
return APR_EINVAL; |
560 |
return APR_EINVAL; |
571 |
} |
561 |
} |
572 |
|
562 |
|
573 |
ptr = (char *)slot->base + slot->desc.size * id; |
563 |
ptr = (char *)slot->base + slot->desc->size * id; |
574 |
if (!ptr) { |
564 |
if (!ptr) { |
575 |
return APR_ENOSHMAVAIL; |
565 |
return APR_ENOSHMAVAIL; |
576 |
} |
566 |
} |
Lines 590-596
static apr_status_t slotmem_get(ap_slotmem_instanc
Link Here
|
590 |
} |
580 |
} |
591 |
|
581 |
|
592 |
inuse = slot->inuse + id; |
582 |
inuse = slot->inuse + id; |
593 |
if (id >= slot->desc.num) { |
583 |
if (id >= slot->desc->num) { |
594 |
return APR_EINVAL; |
584 |
return APR_EINVAL; |
595 |
} |
585 |
} |
596 |
if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { |
586 |
if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { |
Lines 617-623
static apr_status_t slotmem_put(ap_slotmem_instanc
Link Here
|
617 |
} |
607 |
} |
618 |
|
608 |
|
619 |
inuse = slot->inuse + id; |
609 |
inuse = slot->inuse + id; |
620 |
if (id >= slot->desc.num) { |
610 |
if (id >= slot->desc->num) { |
621 |
return APR_EINVAL; |
611 |
return APR_EINVAL; |
622 |
} |
612 |
} |
623 |
if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { |
613 |
if (AP_SLOTMEM_IS_PREGRAB(slot) && !*inuse) { |
Lines 634-640
static apr_status_t slotmem_put(ap_slotmem_instanc
Link Here
|
634 |
|
624 |
|
635 |
static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot) |
625 |
static unsigned int slotmem_num_slots(ap_slotmem_instance_t *slot) |
636 |
{ |
626 |
{ |
637 |
return slot->desc.num; |
627 |
return slot->desc->num; |
638 |
} |
628 |
} |
639 |
|
629 |
|
640 |
static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *slot) |
630 |
static unsigned int slotmem_num_free_slots(ap_slotmem_instance_t *slot) |
Lines 644-650
static unsigned int slotmem_num_free_slots(ap_slot
Link Here
|
644 |
else { |
634 |
else { |
645 |
unsigned int i, counter=0; |
635 |
unsigned int i, counter=0; |
646 |
char *inuse = slot->inuse; |
636 |
char *inuse = slot->inuse; |
647 |
for (i=0; i<slot->desc.num; i++, inuse++) { |
637 |
for (i=0; i<slot->desc->num; i++, inuse++) { |
648 |
if (!*inuse) |
638 |
if (!*inuse) |
649 |
counter++; |
639 |
counter++; |
650 |
} |
640 |
} |
Lines 654-660
static unsigned int slotmem_num_free_slots(ap_slot
Link Here
|
654 |
|
644 |
|
655 |
static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot) |
645 |
static apr_size_t slotmem_slot_size(ap_slotmem_instance_t *slot) |
656 |
{ |
646 |
{ |
657 |
return slot->desc.size; |
647 |
return slot->desc->size; |
658 |
} |
648 |
} |
659 |
|
649 |
|
660 |
static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id) |
650 |
static apr_status_t slotmem_grab(ap_slotmem_instance_t *slot, unsigned int *id) |
Lines 668-679
static apr_status_t slotmem_grab(ap_slotmem_instan
Link Here
|
668 |
|
658 |
|
669 |
inuse = slot->inuse; |
659 |
inuse = slot->inuse; |
670 |
|
660 |
|
671 |
for (i = 0; i < slot->desc.num; i++, inuse++) { |
661 |
for (i = 0; i < slot->desc->num; i++, inuse++) { |
672 |
if (!*inuse) { |
662 |
if (!*inuse) { |
673 |
break; |
663 |
break; |
674 |
} |
664 |
} |
675 |
} |
665 |
} |
676 |
if (i >= slot->desc.num) { |
666 |
if (i >= slot->desc->num) { |
677 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02293) |
667 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02293) |
678 |
"slotmem(%s) grab failed. Num %u/num_free %u", |
668 |
"slotmem(%s) grab failed. Num %u/num_free %u", |
679 |
slot->name, slotmem_num_slots(slot), |
669 |
slot->name, slotmem_num_slots(slot), |
Lines 694-700
static apr_status_t slotmem_fgrab(ap_slotmem_insta
Link Here
|
694 |
return APR_ENOSHMAVAIL; |
684 |
return APR_ENOSHMAVAIL; |
695 |
} |
685 |
} |
696 |
|
686 |
|
697 |
if (id >= slot->desc.num) { |
687 |
if (id >= slot->desc->num) { |
698 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02397) |
688 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02397) |
699 |
"slotmem(%s) fgrab failed. Num %u/num_free %u", |
689 |
"slotmem(%s) fgrab failed. Num %u/num_free %u", |
700 |
slot->name, slotmem_num_slots(slot), |
690 |
slot->name, slotmem_num_slots(slot), |
Lines 721-732
static apr_status_t slotmem_release(ap_slotmem_ins
Link Here
|
721 |
|
711 |
|
722 |
inuse = slot->inuse; |
712 |
inuse = slot->inuse; |
723 |
|
713 |
|
724 |
if (id >= slot->desc.num || !inuse[id] ) { |
714 |
if (id >= slot->desc->num || !inuse[id] ) { |
725 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02294) |
715 |
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02294) |
726 |
"slotmem(%s) release failed. Num %u/inuse[%u] %d", |
716 |
"slotmem(%s) release failed. Num %u/inuse[%u] %d", |
727 |
slot->name, slotmem_num_slots(slot), |
717 |
slot->name, slotmem_num_slots(slot), |
728 |
id, (int)inuse[id]); |
718 |
id, (int)inuse[id]); |
729 |
if (id >= slot->desc.num) { |
719 |
if (id >= slot->desc->num) { |
730 |
return APR_EINVAL; |
720 |
return APR_EINVAL; |
731 |
} else { |
721 |
} else { |
732 |
return APR_NOTFOUND; |
722 |
return APR_NOTFOUND; |
Lines 759-800
static const ap_slotmem_provider_t *slotmem_shm_ge
Link Here
|
759 |
return (&storage); |
749 |
return (&storage); |
760 |
} |
750 |
} |
761 |
|
751 |
|
762 |
/* initialise the global pool */ |
752 |
/* Initialize or reuse the retained slotmems list, and register the |
763 |
static void slotmem_shm_initgpool(apr_pool_t *p) |
753 |
* cleanup to make sure the persisted SHMs are stored and the retained |
|
|
754 |
* data are up to date on next restart/stop. |
755 |
*/ |
756 |
static int pre_config(apr_pool_t *p, apr_pool_t *plog, |
757 |
apr_pool_t *ptemp) |
764 |
{ |
758 |
{ |
765 |
gpool = p; |
759 |
void *is_startup = NULL; |
766 |
} |
760 |
const char *retained_key = "mod_slotmem_shm"; |
767 |
|
761 |
|
768 |
/* Add the pool_clean routine */ |
762 |
retained_globallistmem = ap_retained_data_get(retained_key); |
769 |
static void slotmem_shm_initialize_cleanup(apr_pool_t *p) |
763 |
if (!retained_globallistmem) { |
770 |
{ |
764 |
retained_globallistmem = |
771 |
apr_pool_cleanup_register(p, &globallistmem, cleanup_slotmem, |
765 |
ap_retained_data_create(retained_key, |
|
|
766 |
sizeof *retained_globallistmem); |
767 |
} |
768 |
globallistmem = *retained_globallistmem; |
769 |
|
770 |
if (ap_state_query(AP_SQ_MAIN_STATE) != AP_SQ_MS_CREATE_PRE_CONFIG) { |
771 |
gpool = ap_pglobal; |
772 |
} |
773 |
else { |
774 |
is_startup = (void *)1; |
775 |
gpool = p; |
776 |
} |
777 |
|
778 |
apr_pool_cleanup_register(p, is_startup, cleanup_slotmem, |
772 |
apr_pool_cleanup_null); |
779 |
apr_pool_cleanup_null); |
773 |
} |
|
|
774 |
|
780 |
|
775 |
/* |
|
|
776 |
* Make sure the shared memory is cleaned |
777 |
*/ |
778 |
static int post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, |
779 |
server_rec *s) |
780 |
{ |
781 |
slotmem_shm_initialize_cleanup(p); |
782 |
return OK; |
781 |
return OK; |
783 |
} |
782 |
} |
784 |
|
783 |
|
785 |
static int pre_config(apr_pool_t *p, apr_pool_t *plog, |
|
|
786 |
apr_pool_t *ptemp) |
787 |
{ |
788 |
slotmem_shm_initgpool(p); |
789 |
return OK; |
790 |
} |
791 |
|
792 |
static void ap_slotmem_shm_register_hook(apr_pool_t *p) |
784 |
static void ap_slotmem_shm_register_hook(apr_pool_t *p) |
793 |
{ |
785 |
{ |
794 |
const ap_slotmem_provider_t *storage = slotmem_shm_getstorage(); |
786 |
const ap_slotmem_provider_t *storage = slotmem_shm_getstorage(); |
795 |
ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shm", |
787 |
ap_register_provider(p, AP_SLOTMEM_PROVIDER_GROUP, "shm", |
796 |
AP_SLOTMEM_PROVIDER_VERSION, storage); |
788 |
AP_SLOTMEM_PROVIDER_VERSION, storage); |
797 |
ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_LAST); |
|
|
798 |
ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE); |
789 |
ap_hook_pre_config(pre_config, NULL, NULL, APR_HOOK_MIDDLE); |
799 |
} |
790 |
} |
800 |
|
791 |
|