mod_socache_shmcb.c revision d2fcf1d01ba9f36b78eb7b66fa5af8237b79ac70
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Licensed to the Apache Software Foundation (ASF) under one or more
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * contributor license agreements. See the NOTICE file distributed with
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * this work for additional information regarding copyright ownership.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The ASF licenses this file to You under the Apache License, Version 2.0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * (the "License"); you may not use this file except in compliance with
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the License. You may obtain a copy of the License at
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless required by applicable law or agreed to in writing, software
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distributed under the License is distributed on an "AS IS" BASIS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * See the License for the specific language governing permissions and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * limitations under the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* XXX Unfortunately, there are still many unsigned ints in use here, so we
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * XXX cannot allow more than UINT_MAX. Since some of the ints are exposed in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * XXX public interfaces, a simple search and replace is not enough.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * XXX It should be possible to extend that so that the total cache size can
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * XXX be APR_SIZE_MAX and only the object size needs to be smaller than
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * XXX UINT_MAX.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define SHMCB_MAX_SIZE (UINT_MAX<APR_SIZE_MAX ? UINT_MAX : APR_SIZE_MAX)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define ALIGNED_HEADER_SIZE APR_ALIGN_DEFAULT(sizeof(SHMCBHeader))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define ALIGNED_SUBCACHE_SIZE APR_ALIGN_DEFAULT(sizeof(SHMCBSubcache))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define ALIGNED_INDEX_SIZE APR_ALIGN_DEFAULT(sizeof(SHMCBIndex))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Header structure - the start of the shared-mem segment
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Stats for cache operations */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long stat_stores;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long stat_replaced;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long stat_expiries;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned long stat_scrolled;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Number of subcaches */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* How many indexes each subcache's queue has */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int index_num;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* How large each subcache is, including the queue and data */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* How far into each subcache the data area is (optimisation) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* How large the data area in each subcache is (optimisation) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Subcache structure - the start of each subcache, followed by
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * indexes then data
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* The start position and length of the cyclic buffer of indexes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Same for the data area */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Index structure - each subcache has an array of these
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* absolute time this entry expires */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* location within the subcache's data area */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int data_pos;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* size (most logic ignores this, we keep it only to minimise memcpy) */
f8fc4173f3b9715e5945b668ba511b77573dc1d1minfrin unsigned int data_used;
f8fc4173f3b9715e5945b668ba511b77573dc1d1minfrin /* length of the used data which contains the id */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int id_len;
f8fc4173f3b9715e5945b668ba511b77573dc1d1minfrin /* Used to mark explicitly-removed socache entries */
f8fc4173f3b9715e5945b668ba511b77573dc1d1minfrin unsigned char removed;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* The SHM data segment is of fixed size and stores data as follows.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * [ SHMCBHeader | Subcaches ]
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The SHMCBHeader header structure stores metadata concerning the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * cache and the contained subcaches.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Subcaches is a hash table of header->subcache_num SHMCBSubcache
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * structures. The hash table is indexed by SHMCB_MASK(id). Each
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SHMCBSubcache structure has a fixed size (header->subcache_size),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * which is determined at creation time, and looks like the following:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * [ SHMCBSubcache | Indexes | Data ]
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Each subcache is prefixed by the SHMCBSubcache structure.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The subcache's "Data" segment is a single cyclic data buffer, of
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * total size header->subcache_data_size; data inside is referenced
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * using byte offsets. The offset marking the beginning of the cyclic
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * buffer is subcache->data_pos; the buffer's length is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * subcache->data_used.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * "Indexes" is an array of header->index_num SHMCBIndex structures,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * which is used as a cyclic queue; subcache->idx_pos gives the array
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * index of the first in use, subcache->idx_used gives the number in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * use. Both ->idx_* values have a range of [0, header->index_num)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Each in-use SHMCBIndex structure represents a single cached object.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The ID and data segment are stored consecutively in the subcache's
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * cyclic data buffer. The "Data" segment can thus be seen to
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * look like this, for example
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * offset: [ 0 1 2 3 4 5 6 ...
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * contents:[ ID1 Data1 ID2 Data2 ID3 ...
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * where the corresponding indices would look like:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * idx1 = { data_pos = 0, data_used = 3, id_len = 1, ...}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * idx2 = { data_pos = 3, data_used = 3, id_len = 1, ...}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* This macro takes a pointer to the header and a zero-based index and returns
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * a pointer to the corresponding subcache. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (SHMCBSubcache *)(((unsigned char *)(pHeader)) + \
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* This macro takes a pointer to the header and an id and returns a
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * pointer to the corresponding subcache. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SHMCB_SUBCACHE((pHeader), *(id) & ((pHeader)->subcache_num - 1))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* This macro takes the same params as the last, generating two outputs for use
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * in ap_log_error(...). */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* This macro takes a pointer to a subcache and a zero-based index and returns
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * a pointer to the corresponding SHMCBIndex. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* This macro takes a pointer to the header and a subcache and returns a
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * pointer to the corresponding data area. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ((unsigned char *)(pSubcache) + (pHeader)->subcache_data_offset)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Cyclic functions - assists in "wrap-around"/modulo logic
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Addition modulo 'mod' */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Subtraction (or "distance between") modulo 'mod' */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* A "normal-to-cyclic" memcpy. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void shmcb_cyclic_ntoc_memcpy(unsigned int buf_size, unsigned char *data,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int dest_offset, const unsigned char *src,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int src_len)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* It be copied all in one go */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Copy the two splits */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memcpy(data + dest_offset, src, buf_size - dest_offset);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* A "cyclic-to-normal" memcpy. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void shmcb_cyclic_cton_memcpy(unsigned int buf_size, unsigned char *dest,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const unsigned char *data, unsigned int src_offset,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int src_len)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* It be copied all in one go */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Copy the two splits */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memcpy(dest, data + src_offset, buf_size - src_offset);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* A memcmp against a cyclic data buffer. Compares SRC of length
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SRC_LEN against the contents of cyclic buffer DATA (which is of
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * size BUF_SIZE), starting at offset DEST_OFFSET. Got that? Good. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int shmcb_cyclic_memcmp(unsigned int buf_size, unsigned char *data,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int dest_offset,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const unsigned char *src,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int src_len)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* It be compared all in one go */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Compare the two splits */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes diff = memcmp(data + dest_offset, src, buf_size - dest_offset);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Prototypes for low-level subcache operations */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void shmcb_subcache_expire(server_rec *, SHMCBHeader *, SHMCBSubcache *,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Returns zero on success, non-zero on failure. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int shmcb_subcache_store(server_rec *s, SHMCBHeader *header,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Returns zero on success, non-zero on failure. */
e18ba90a1e610b43062e90cfa8bf0c1edcad7a49bnicholesstatic int shmcb_subcache_retrieve(server_rec *, SHMCBHeader *, SHMCBSubcache *,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Returns zero on success, non-zero on failure. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int shmcb_subcache_remove(server_rec *, SHMCBHeader *, SHMCBSubcache *,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const unsigned char *, unsigned int);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Returns result of the (iterator)() call, zero is success (continue) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t shmcb_subcache_iterate(ap_socache_instance_t *instance,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned char **buf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * High-Level "handlers" as per ssl_scache.c
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * subcache internals are deferred to shmcb_subcache_*** functions lower down
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *socache_shmcb_create(ap_socache_instance_t **context,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *arg,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Allocate the context. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Use defaults. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->data_file = path = ap_runtime_dir_relative(p, arg);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Invalid argument: no closing parenthesis or cache size "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "missing after pathname with parenthesis";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Invalid argument: cache size not numerical";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Invalid argument: size has to be >= 8192 bytes";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return apr_psprintf(tmp, "Invalid argument: size has "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "to be < %" APR_SIZE_T_FMT " bytes on this platform",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Invalid argument: no opening parenthesis";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t socache_shmcb_init(ap_socache_instance_t *ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Create shared memory segment */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *path = apr_pstrcat(p, DEFAULT_SHMCB_PREFIX, namespace,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->data_file = ap_runtime_dir_relative(p, path);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Use anonymous shm by default, fall back on name-based. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_shm_create(&ctx->shm, ctx->shm_size, NULL, p);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* If anon shm isn't supported, fail if no named file was
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * configured successfully; the ap_runtime_dir_relative call
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * above will return NULL for invalid paths. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00818)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not use default path '%s' for shmcb socache",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* For a name-based segment, remove it first in case of a
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * previous unclean shutdown. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_shm_create(&ctx->shm, ctx->shm_size, ctx->data_file, p);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00819)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not allocate shared memory segment for shmcb "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* the segment is ridiculously small, bail out */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00820)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shared memory segment too small");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00821)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes " bytes of shared memory",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Discount the header */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Select index size based on average object size hints, if given. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes avg_obj_size = hints && hints->avg_obj_size ? hints->avg_obj_size : 150;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes avg_id_len = hints && hints->avg_id_len ? hints->avg_id_len : 30;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes num_idx = (shm_segsize) / (avg_obj_size + avg_id_len);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while ((num_idx / num_subcache) < (2 * num_subcache))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00822)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes " including header), recommending %u subcaches, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* we're still too small, bail out */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00823)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shared memory segment too small");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* OK, we're sorted */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Convert the subcache size (in bytes) to a value that is suitable for
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * structure alignment on the host platform, by rounding down if necessary. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes header->subcache_size = (size_t)(shm_segsize / num_subcache);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (header->subcache_size != APR_ALIGN_DEFAULT(header->subcache_size)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes header->subcache_size = APR_ALIGN_DEFAULT(header->subcache_size) -
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes header->subcache_data_offset = ALIGNED_SUBCACHE_SIZE +
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes header->subcache_data_size = header->subcache_size -
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Output trace info */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00824)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shmcb_init_memory choices follow");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00825)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00826)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00827)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "subcache_data_offset = %u", header->subcache_data_offset);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00828)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "subcache_data_size = %u", header->subcache_data_size);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00829)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* The header is done, make the caches empty */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (loop = 0; loop < header->subcache_num; loop++) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(00830)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Shared memory socache initialised");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Success ... */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void socache_shmcb_destroy(ap_socache_instance_t *ctx, server_rec *s)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t socache_shmcb_store(ap_socache_instance_t *ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned char *encoded,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int len_encoded,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00831)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "socache_shmcb_store (0x%02x -> subcache %d)",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* XXX: Says who? Why shouldn't this be acceptable, or padded if not? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00832) "unusably short id provided "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes tryreplace = shmcb_subcache_remove(s, header, subcache, id, idlen);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (shmcb_subcache_store(s, header, subcache, encoded,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00833)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "can't store an socache entry!");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00834)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "leaving socache_shmcb_store successfully");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t socache_shmcb_retrieve(ap_socache_instance_t *ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00835)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "socache_shmcb_retrieve (0x%02x -> subcache %d)",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Get the entry corresponding to the id, if it exists. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = shmcb_subcache_retrieve(s, header, subcache, id, idlen,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00836)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "leaving socache_shmcb_retrieve successfully");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t socache_shmcb_remove(ap_socache_instance_t *ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00837)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "socache_shmcb_remove (0x%02x -> subcache %d)",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00838) "unusably short id provided "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (shmcb_subcache_remove(s, header, subcache, id, idlen) == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00839)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "leaving socache_shmcb_remove successfully");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void socache_shmcb_status(ap_socache_instance_t *ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int loop, total = 0, cache_total = 0, non_empty_subcaches = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_time_t idx_expiry, min_expiry = 0, max_expiry = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00840) "inside shmcb_status");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Perform the iteration inside the mutex to avoid corruption or invalid
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * pointer arithmetic. The rest of our logic uses read-only header data so
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * doesn't need the lock. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Iterate over the subcaches */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (loop = 0; loop < header->subcache_num; loop++) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SHMCBIndex *idx = SHMCB_INDEX(subcache, subcache->idx_pos);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes max_expiry = ((idx_expiry > max_expiry) ? idx_expiry : max_expiry);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes min_expiry = ((idx_expiry < min_expiry) ? idx_expiry : min_expiry);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes cache_pct = (100 * cache_total) / (header->subcache_data_size *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Generate Output */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "cache type: <b>SHMCB</b>, shared memory: <b>%" APR_SIZE_T_FMT "</b> "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "bytes, current entries: <b>%d</b><br>",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "subcaches: <b>%d</b>, indexes per subcache: <b>%d</b><br>",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_time_t average_expiry = (apr_time_t)(expiry_total / (double)non_empty_subcaches);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "time left on oldest entries' objects: ");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "avg: <b>%d</b> seconds, (range: %d...%d)<br>",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "expiry_threshold: <b>Calculation error!</b><br>");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "index usage: <b>%d%%</b>, cache usage: <b>%d%%</b><br>",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "total entries stored since starting: <b>%lu</b><br>",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "total entries replaced since starting: <b>%lu</b><br>",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "total entries expired since starting: <b>%lu</b><br>",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "total (pre-expiry) entries scrolled out of the cache: "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "total retrieves since starting: <b>%lu</b> hit, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<b>%lu</b> miss<br>", header->stat_retrieves_hit,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "total removes since starting: <b>%lu</b> hit, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheSharedMemory: %" APR_SIZE_T_FMT "\n",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheCurrentEntries: %d\n", total);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheSubcaches: %d\n", header->subcache_num);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheIndexesPerSubcaches: %d\n", header->index_num);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_time_t average_expiry = (apr_time_t)(expiry_total / (double)non_empty_subcaches);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheTimeLeftOldestAvg: %d\n", (int)apr_time_sec(average_expiry - now));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheTimeLeftOldestMin: %d\n", (int)apr_time_sec(min_expiry - now));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheTimeLeftOldestMax: %d\n", (int)apr_time_sec(max_expiry - now));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheIndexUsage: %d%%\n", index_pct);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheStoreCount: %lu\n", header->stat_stores);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheReplaceCount: %lu\n", header->stat_replaced);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheExpireCount: %lu\n", header->stat_expiries);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheDiscardCount: %lu\n", header->stat_scrolled);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheRetrieveHitCount: %lu\n", header->stat_retrieves_hit);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheRetrieveMissCount: %lu\n", header->stat_retrieves_miss);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheRemoveHitCount: %lu\n", header->stat_removes_hit);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_rprintf(r, "CacheRemoveMissCount: %lu\n", header->stat_removes_miss);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00841) "leaving shmcb_status");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t socache_shmcb_iterate(ap_socache_instance_t *instance,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int loop;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Perform the iteration inside the mutex to avoid corruption or invalid
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * pointer arithmetic. The rest of our logic uses read-only header data so
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * doesn't need the lock. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Iterate over the subcaches */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (loop = 0; loop < header->subcache_num && rv == APR_SUCCESS; loop++) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = shmcb_subcache_iterate(instance, s, userctx, header, subcache,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Subcache-level cache operations
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void shmcb_subcache_expire(server_rec *s, SHMCBHeader *header,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* not removed and not expired yet, we're done iterating */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new_idx_pos = SHMCB_CYCLIC_INCREMENT(new_idx_pos, 1, header->index_num);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Nothing to do */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00842)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "expiring %u and reclaiming %u removed socache entries",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* We're expiring everything, piece of cake */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* There remain other indexes, so we can use idx to adjust 'data' */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int diff = SHMCB_CYCLIC_SPACE(subcache->data_pos,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Adjust the indexes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Adjust the data area */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00843)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "we now have %u socache entries", subcache->idx_used);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int shmcb_subcache_store(server_rec *s, SHMCBHeader *header,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Sanity check the input */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00844)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "inserting socache entry larger (%d) than subcache data area (%d)",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* First reclaim space from removed and expired records. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes shmcb_subcache_expire(s, header, subcache, apr_time_now());
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Loop until there is enough space to insert
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * XXX: This should first compress out-of-order expiries and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * removed records, and then force-remove oldest-first
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (header->subcache_data_size - subcache->data_used < total_len
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int loop = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00845)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "about to force-expire, subcache: idx_used=%d, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "data_used=%d", subcache->idx_used, subcache->data_used);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Adjust the indexes by one */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes subcache->idx_pos = SHMCB_CYCLIC_INCREMENT(subcache->idx_pos, 1,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* There's nothing left */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Adjust the data */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes subcache->data_used -= SHMCB_CYCLIC_SPACE(idx->data_pos, idx2->data_pos,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Loop admin */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes } while (header->subcache_data_size - subcache->data_used < total_len);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00846)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "finished force-expire, subcache: idx_used=%d, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "data_used=%d", subcache->idx_used, subcache->data_used);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* HERE WE ASSUME THAT THE NEW ENTRY SHOULD GO ON THE END! I'M NOT
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * CHECKING WHETHER IT SHOULD BE GENUINELY "INSERTED" SOMEWHERE.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * We aught to fix that. httpd (never mind third party modules)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * does not promise to perform any processing in date order
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * (c.f. FAQ "My log entries are not in date order!")
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Insert the id */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes id_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes shmcb_cyclic_ntoc_memcpy(header->subcache_data_size,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Insert the data */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes data_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes shmcb_cyclic_ntoc_memcpy(header->subcache_data_size,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Insert the index */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes new_idx = SHMCB_CYCLIC_INCREMENT(subcache->idx_pos, subcache->idx_used,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00847)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "insert happened at idx=%d, data=(%u:%u)", new_idx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00848)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "finished insert, subcache: idx_pos/idx_used=%d/%d, "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int shmcb_subcache_retrieve(server_rec *s, SHMCBHeader *header,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int pos;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int loop = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Only consider 'idx' if the id matches, and the "removed"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * flag isn't set, and the record is not expired.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Check the data length too to avoid a buffer overflow
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * in case of corruption, which should be impossible,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * but it's cheap to be safe. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && shmcb_cyclic_memcmp(header->subcache_data_size,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00849)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int data_offset;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Find the offset of the data segment, after the id */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes data_offset = SHMCB_CYCLIC_INCREMENT(idx->data_pos,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Copy out the data */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes shmcb_cyclic_cton_memcpy(header->subcache_data_size,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Already stale, quietly remove and treat as not-found */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00850)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shmcb_subcache_retrieve discarding expired entry");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Increment */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00851)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shmcb_subcache_retrieve found no match");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int shmcb_subcache_remove(server_rec *s, SHMCBHeader *header,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const unsigned char *id,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int idlen)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int pos;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int loop = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Only consider 'idx' if the id matches, and the "removed"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * flag isn't set. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes && shmcb_cyclic_memcmp(header->subcache_data_size,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00852)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "possible match at idx=%d, data=%d", pos, idx->data_pos);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Found the matching entry, remove it quietly. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00853)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shmcb_subcache_remove removing matching entry");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Increment */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t shmcb_subcache_iterate(ap_socache_instance_t *instance,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned char **buf,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int pos;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned int loop = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Only consider 'idx' if the "removed" flag isn't set. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00854)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned char *dest;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Find the offset of the data segment, after the id */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes data_offset = SHMCB_CYCLIC_INCREMENT(idx->data_pos,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Grow to ~150% of this buffer requirement on resize
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * always using APR_ALIGN_DEFAULT sized pages
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *buf_len = buf_req + APR_ALIGN_DEFAULT(buf_req / 2);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Copy out the data, because it's potentially cyclic */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes shmcb_cyclic_cton_memcpy(header->subcache_data_size, id,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes shmcb_cyclic_cton_memcpy(header->subcache_data_size, dest,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = iterator(instance, s, userctx, id, idx->id_len,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s, APLOGNO(00855)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shmcb entry iterated");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Already stale, quietly remove and treat as not-found */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(00856)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "shmcb_subcache_iterate discarding expired entry");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Increment */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const ap_socache_provider_t socache_shmcb = {
5aa455d45abacfa675c88d4ff53fbe97c44ce545bnicholes ap_register_provider(p, AP_SOCACHE_PROVIDER_GROUP, "shmcb",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Also register shmcb under the default provider name. */