Пример #1
0
static void init_shm(lua_State *L, lua_apr_shm *object)
{
  object->base = apr_shm_baseaddr_get(object->handle);
  object->size = apr_shm_size_get(object->handle);
  object->last_op = &object->input.buffer;
  init_unmanaged_buffers(L,
      &object->input, &object->output,
      object->base, object->size);
}
apr_status_t upload_progress_cache_init(apr_pool_t *pool, ServerConfig *config)
{

#if APR_HAS_SHARED_MEMORY
    apr_status_t result;
    apr_size_t size;
    upload_progress_cache_t *cache;
    apr_rmm_off_t block;

    if (config->cache_file) {
        /* Remove any existing shm segment with this name. */
        apr_shm_remove(config->cache_file, config->pool);
    }

    size = APR_ALIGN_DEFAULT(config->cache_bytes);
    result = apr_shm_create(&config->cache_shm, size, config->cache_file, config->pool);
    if (result != APR_SUCCESS) {
        return result;
    }

    /* Determine the usable size of the shm segment. */
    size = apr_shm_size_get(config->cache_shm);

    /* This will create a rmm "handler" to get into the shared memory area */
    result = apr_rmm_init(&config->cache_rmm, NULL,
                          apr_shm_baseaddr_get(config->cache_shm), size,
                          config->pool);
    if (result != APR_SUCCESS) {
        return result;
    }

    apr_pool_cleanup_register(config->pool, config , upload_progress_cache_module_kill, apr_pool_cleanup_null);
    
    /* init cache object */
    CACHE_LOCK();
    block = apr_rmm_calloc(config->cache_rmm, sizeof(upload_progress_cache_t));
    cache = block ? (upload_progress_cache_t *)apr_rmm_addr_get(config->cache_rmm, block) : NULL;
    if(cache == NULL) {
      CACHE_UNLOCK();
      return 0;
    }
    cache->head = NULL;
    config->cache_offset = block;
    config->cache = cache;
    CACHE_UNLOCK();
    
#endif

    return APR_SUCCESS;
}
Пример #3
0
static void test_anon(abts_case *tc, void *data)
{
    apr_proc_t proc;
    apr_status_t rv;
    apr_shm_t *shm;
    apr_size_t retsize;
    int cnt, i;
    int recvd;

    rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p);
    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
    ABTS_PTR_NOTNULL(tc, shm);

    retsize = apr_shm_size_get(shm);
    ABTS_INT_EQUAL(tc, SHARED_SIZE, retsize);

    boxes = apr_shm_baseaddr_get(shm);
    ABTS_PTR_NOTNULL(tc, boxes);

    rv = apr_proc_fork(&proc, p);
    if (rv == APR_INCHILD) { /* child */
        int num = msgwait(5, 0, N_BOXES);
        /* exit with the number of messages received so that the parent
         * can check that all messages were received.
         */
        exit(num);
    }
    else if (rv == APR_INPARENT) { /* parent */
        i = N_BOXES;
        cnt = 0;
        while (cnt++ < N_MESSAGES) {
            if ((i-=3) < 0) {
                i += N_BOXES; /* start over at the top */
            }
            msgput(i, MSG);
            apr_sleep(apr_time_make(0, 10000));
        }
    }
    else {
        ABTS_FAIL(tc, "apr_proc_fork failed");
    }
    /* wait for the child */
    rv = apr_proc_wait(&proc, &recvd, NULL, APR_WAIT);
    ABTS_INT_EQUAL(tc, N_MESSAGES, recvd);

    rv = apr_shm_destroy(shm);
    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
}
Пример #4
0
DownloadFlowController *DownloadFlowController::get_instance(apr_shm_t *shm)
{
    DownloadFlowController *flow_controller;

#ifdef DEBUG
    if (apr_shm_size_get(shm) != get_memory_size()) {
        THROW(MESSAGE_SHM_SIZE_INVALID);
    }
#endif

    flow_controller =
        reinterpret_cast<DownloadFlowController *>(apr_shm_baseaddr_get(shm));
    new(flow_controller) DownloadFlowController;

    return flow_controller;
}
Пример #5
0
static void test_check_size(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_shm_t *shm = NULL;
    apr_size_t retsize;

    rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p);
    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
    ABTS_PTR_NOTNULL(tc, shm);

    retsize = apr_shm_size_get(shm);
    ABTS_SIZE_EQUAL(tc, SHARED_SIZE, retsize);

    rv = apr_shm_destroy(shm);
    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv);
}
Пример #6
0
apr_status_t util_ldap_cache_init(apr_pool_t *pool, util_ldap_state_t *st)
{
#if APR_HAS_SHARED_MEMORY
    apr_status_t result;
    apr_size_t size;

    if (st->cache_bytes > 0) {
        if (st->cache_file) {
            /* Remove any existing shm segment with this name. */
            apr_shm_remove(st->cache_file, st->pool);
        }

        size = APR_ALIGN_DEFAULT(st->cache_bytes);

        result = apr_shm_create(&st->cache_shm, size, st->cache_file, st->pool);
        if (result != APR_SUCCESS) {
            return result;
        }

        /* Determine the usable size of the shm segment. */
        size = apr_shm_size_get(st->cache_shm);

        /* This will create a rmm "handler" to get into the shared memory area */
        result = apr_rmm_init(&st->cache_rmm, NULL,
                              apr_shm_baseaddr_get(st->cache_shm), size,
                              st->pool);
        if (result != APR_SUCCESS) {
            return result;
        }
    }

#endif

    apr_pool_cleanup_register(st->pool, st , util_ldap_cache_module_kill, apr_pool_cleanup_null);

    st->util_ldap_cache =
        util_ald_create_cache(st,
                              st->search_cache_size,
                              st->search_cache_ttl,
                              util_ldap_url_node_hash,
                              util_ldap_url_node_compare,
                              util_ldap_url_node_copy,
                              util_ldap_url_node_free,
                              util_ldap_url_node_display);
    return APR_SUCCESS;
}
Пример #7
0
apr_status_t util_ldap_cache_init(apr_pool_t *pool, util_ldap_state_t *st)
{
#if APR_HAS_SHARED_MEMORY
    apr_status_t result;
    apr_size_t size;

    size = APR_ALIGN_DEFAULT(st->cache_bytes);

    result = apr_shm_create(&st->cache_shm, size, st->cache_file, st->pool);
    if (result == APR_EEXIST) {
        /*
         * The cache could have already been created (i.e. we may be a child process).  See
         * if we can attach to the existing shared memory
         */
        result = apr_shm_attach(&st->cache_shm, st->cache_file, st->pool);
    } 
    if (result != APR_SUCCESS) {
        return result;
    }

    /* Determine the usable size of the shm segment. */
    size = apr_shm_size_get(st->cache_shm);

    /* This will create a rmm "handler" to get into the shared memory area */
    result = apr_rmm_init(&st->cache_rmm, NULL, 
                          apr_shm_baseaddr_get(st->cache_shm), size, 
                          st->pool);
    if (result != APR_SUCCESS) {
        return result;
    }

#endif

    apr_pool_cleanup_register(st->pool, st , util_ldap_cache_module_kill, apr_pool_cleanup_null);

    st->util_ldap_cache =
        util_ald_create_cache(st,
                              util_ldap_url_node_hash,
                              util_ldap_url_node_compare,
                              util_ldap_url_node_copy,
                              util_ldap_url_node_free,
                              util_ldap_url_node_display);
    return APR_SUCCESS;
}
Пример #8
0
/* If detach is non-zero, this is a separate child process,
 * if zero, it is a forked child.
 */
apr_status_t ap_reopen_scoreboard(apr_pool_t *p, apr_shm_t **shm, int detached)
{
#if APR_HAS_SHARED_MEMORY
    if (!detached) {
        return APR_SUCCESS;
    }
    if (apr_shm_size_get(ap_scoreboard_shm) < scoreboard_size) {
        ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL,
                     "Fatal error: shared scoreboard too small for child!");
        apr_shm_detach(ap_scoreboard_shm);
        ap_scoreboard_shm = NULL;
        return APR_EINVAL;
    }
    /* everything will be cleared shortly */
    if (*shm) {
        *shm = ap_scoreboard_shm;
    }
#endif
    return APR_SUCCESS;
}
Пример #9
0
/* Set up startup-time initialization */
static int vlimit_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{
    VLIMIT_DEBUG_SYSLOG("vlimit_init: ", MODULE_NAME " " MODULE_VERSION " started.", p);

    if(apr_file_open(&vlimit_log_fp, VLIMIT_LOG_FILE, APR_WRITE|APR_APPEND|APR_CREATE,
           APR_OS_DEFAULT, p) != APR_SUCCESS){
        return OK;
    }

    apr_status_t status;
    apr_size_t retsize;
    apr_size_t shm_size;
    int t;

    SHM_DATA *shm_data = NULL;

    shm_size = (apr_size_t) (sizeof(shm_data) + sizeof(shm_data->file_stat_shm) + sizeof(shm_data->ip_stat_shm)) * (conf_counter + 1);

    //Create global mutex
    status = apr_global_mutex_create(&vlimit_mutex, NULL, APR_LOCK_DEFAULT, p);
    if(status != APR_SUCCESS){
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error creating global mutex.", p);
        return status;
    }
#ifdef AP_NEED_SET_MUTEX_PERMS
    status = unixd_set_global_mutex_perms(vlimit_mutex);
    if(status != APR_SUCCESS){
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error xrent could not set permissions on global mutex.", p);
        return status;
    }
#endif

    if(apr_global_mutex_child_init(&vlimit_mutex, NULL, p))
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "global mutex attached.", p);

    /* If there was a memory block already assigned.. destroy it */
    if (shm) {
        status = apr_shm_destroy(shm);
        if (status != APR_SUCCESS) {
            VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Couldn't destroy old memory block", p);
            return status;
        } else {
            VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Old Shared memory block, destroyed.", p);
        }
    }

    /* Create shared memory block */
    status = apr_shm_create(&shm, shm_size, NULL, p);
    if (status != APR_SUCCESS) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error creating shm block", p);
        return status;
    }


    /* Check size of shared memory block */
    retsize = apr_shm_size_get(shm);
    if (retsize != shm_size) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init: ", "Error allocating shared memory block", p);
        return status;
    }
    /* Init shm block */
    shm_base = apr_shm_baseaddr_get(shm);
    if (shm_base == NULL) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init", "Error creating status block.", p);
        return status;
    }
    memset(shm_base, 0, retsize);

    vlimit_debug_log_buf = apr_psprintf(p
        , "Memory Allocated %d bytes (each conf takes %d bytes) MaxClient:%d"
        , (int) retsize
        , (int) (sizeof(shm_data) + sizeof(shm_data->file_stat_shm) + sizeof(shm_data->ip_stat_shm))
        , MAX_CLIENTS
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_init: ", vlimit_debug_log_buf, p);

    if (retsize < (sizeof(shm_data) * conf_counter)) {
        VLIMIT_DEBUG_SYSLOG("vlimit_init ", "Not enough memory allocated!! Giving up" , p);
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    int i;

    for (t = 0; t <= conf_counter; t++) {
        shm_data = shm_base + t;
        for (i = 0; i < MAX_CLIENTS; i++) {
            shm_data->file_stat_shm[i].filename[0] = '\0';
            shm_data->ip_stat_shm[i].address[0]    = '\0';
            shm_data->file_stat_shm[i].counter     = 0;
            shm_data->ip_stat_shm[i].counter       = 0;
        }
    }

    vlimit_debug_log_buf = apr_psprintf(p
        , "%s Version %s - Initialized [%d Conf]"
        , MODULE_NAME
        , MODULE_VERSION
        , conf_counter
    );
    VLIMIT_DEBUG_SYSLOG("vlimit_init: ", vlimit_debug_log_buf, p);

    return OK;
}
Пример #10
0
static void test_named(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_shm_t *shm = NULL;
    apr_size_t retsize;
    apr_proc_t pidproducer, pidconsumer;
    apr_procattr_t *attr1 = NULL, *attr2 = NULL;
    int sent, received;
    apr_exit_why_e why;
    const char *args[4];

    apr_shm_remove(SHARED_FILENAME, p);

    rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p);
    APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv);
    if (rv != APR_SUCCESS) {
        return;
    }
    ABTS_PTR_NOTNULL(tc, shm);

    retsize = apr_shm_size_get(shm);
    ABTS_SIZE_EQUAL(tc, SHARED_SIZE, retsize);

    boxes = apr_shm_baseaddr_get(shm);
    ABTS_PTR_NOTNULL(tc, boxes);

    rv = apr_procattr_create(&attr1, p);
    ABTS_PTR_NOTNULL(tc, attr1);
    APR_ASSERT_SUCCESS(tc, "Couldn't create attr1", rv);

    rv = apr_procattr_cmdtype_set(attr1, APR_PROGRAM_ENV);
    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);

    args[0] = apr_pstrdup(p, "testshmproducer" EXTENSION);
    args[1] = NULL;
    rv = apr_proc_create(&pidproducer, TESTBINPATH "testshmproducer" EXTENSION, args,
                         NULL, attr1, p);
    APR_ASSERT_SUCCESS(tc, "Couldn't launch producer", rv);

    rv = apr_procattr_create(&attr2, p);
    ABTS_PTR_NOTNULL(tc, attr2);
    APR_ASSERT_SUCCESS(tc, "Couldn't create attr2", rv);

    rv = apr_procattr_cmdtype_set(attr2, APR_PROGRAM_ENV);
    APR_ASSERT_SUCCESS(tc, "Couldn't set copy environment", rv);

    args[0] = apr_pstrdup(p, "testshmconsumer" EXTENSION);
    rv = apr_proc_create(&pidconsumer, TESTBINPATH "testshmconsumer" EXTENSION, args, 
                         NULL, attr2, p);
    APR_ASSERT_SUCCESS(tc, "Couldn't launch consumer", rv);

    rv = apr_proc_wait(&pidconsumer, &received, &why, APR_WAIT);
    ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv);
    ABTS_INT_EQUAL(tc, APR_PROC_EXIT, why);

    rv = apr_proc_wait(&pidproducer, &sent, &why, APR_WAIT);
    ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv);
    ABTS_INT_EQUAL(tc, APR_PROC_EXIT, why);

    /* Cleanup before testing that producer and consumer worked correctly.
     * This way, if they didn't succeed, we can just run this test again
     * without having to cleanup manually.
     */
    APR_ASSERT_SUCCESS(tc, "Error destroying shared memory", 
                       apr_shm_destroy(shm));
    
    ABTS_INT_EQUAL(tc, sent, received);

}
Пример #11
0
static apr_status_t test_anon(apr_pool_t *parpool)
{
    apr_status_t rv;
    apr_pool_t *pool;
    apr_shm_t *shm;
    apr_size_t retsize;
    pid_t pid;
    int cnt, i, exit_int;

    rv = apr_pool_create(&pool, parpool);
    if (rv != APR_SUCCESS) {
        fprintf(stderr, "Error creating child pool\n");
        return rv;
    }

    printf("Creating anonymous shared memory block (%"
           APR_SIZE_T_FMT " bytes)........", SHARED_SIZE);
    rv = apr_shm_create(&shm, SHARED_SIZE, NULL, pool);
    if (rv != APR_SUCCESS) {
        fprintf(stderr, "Error allocating shared memory block\n");
        return rv;
    }
    fprintf(stdout, "OK\n");

    printf("Checking size...%" APR_SIZE_T_FMT " bytes...",
           retsize = apr_shm_size_get(shm));
    if (retsize != SHARED_SIZE) {
        fprintf(stderr, "Error allocating shared memory block\n");
        return rv;
    }
    fprintf(stdout, "OK\n");

    printf("Allocating shared mbox memory for %d boxes ..............",
           N_BOXES);
    boxes = apr_shm_baseaddr_get(shm);
    if (boxes == NULL) {
        fprintf(stderr, "Error creating message boxes.\n");
        return rv;
    }
    fprintf(stdout, "OK\n");

    printf("Shared Process Test (child/parent)\n");
    pid = fork();
    if (pid == 0) { /* child */
        msgwait(5, 0, N_BOXES);
        exit(0);
    }
    else if (pid > 0) { /* parent */
        i = N_BOXES;
        cnt = N_MESSAGES;
        while (--cnt > 0) {
            if ((i-=3) < 0) {
                i += N_BOXES; /* start over at the top */
            }
            msgput(i, "Sending a message\n");
            apr_sleep(apr_time_make(0, 10000));
        }
    }
    else {
        printf("Error creating a child process\n");
        return errno;
    }
    /* wait for the child */
    printf("Waiting for child to exit.\n");
    if (waitpid(pid, &exit_int, 0) < 0) {
        return errno;
    }

    printf("Destroying shared memory segment...");
    rv = apr_shm_destroy(shm);
    if (rv != APR_SUCCESS) {
        printf("FAILED\n");
        return rv;
    }
    printf("OK\n");

    apr_pool_destroy(pool);

    return APR_SUCCESS;
}
Пример #12
0
static apr_status_t test_named(apr_pool_t *parpool)
{
    apr_status_t rv;
    apr_pool_t *pool;
    apr_shm_t *shm;
    apr_size_t retsize;
    pid_t pidproducer, pidconsumer;
    int exit_int;

    rv = apr_pool_create(&pool, parpool);
    if (rv != APR_SUCCESS) {
        fprintf(stderr, "Error creating child pool\n");
        return rv;
    }

    printf("Creating named shared memory block (%"
           APR_SIZE_T_FMT " bytes)........", SHARED_SIZE);
    rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, pool);
    if (rv != APR_SUCCESS) {
        fprintf(stderr, "Error allocating shared memory block\n");
        return rv;
    }
    fprintf(stdout, "OK\n");

    printf("Checking size...%" APR_SIZE_T_FMT " bytes...",
           retsize = apr_shm_size_get(shm));
    if (retsize != SHARED_SIZE) {
        fprintf(stderr, "Error allocating shared memory block\n");
        return rv;
    }
    fprintf(stdout, "OK\n");

    printf("Allocating shared mbox memory for %d boxes ..............",
           N_BOXES);
    boxes = apr_shm_baseaddr_get(shm);
    if (boxes == NULL) {
        fprintf(stderr, "Error creating message boxes.\n");
        return rv;
    }
    fprintf(stdout, "OK\n");

    printf("fork()ing and exec()ing children:\n");
    pidproducer = fork();
    if (pidproducer == 0) { /* child */
        /* FIXME: exec a producer */
        printf("starting consumer.....\n");
        if (execlp("testshmconsumer", "testshmconsumer", (char*)0) < 0) {
            return errno;
        }
    }
    else if (pidproducer > 0) { /* parent */
        /* fork another child */
        pidconsumer = fork();
        if (pidconsumer == 0) { /* child */
            /* FIXME: exec a producer */
            printf("starting producer.....\n");
            if (execlp("testshmproducer", "testshmproducer", (char*)0) < 0) {
                return errno;
            }
        }
        else if (pidconsumer < 0) { /* parent */
            printf("Error creating a child process\n");
            return errno;
        }
    }
    else {
        printf("Error creating a child process\n");
        return errno;
    }
    /* wait for the child */
    printf("Waiting for producer to exit.\n");
    if (waitpid(pidconsumer, &exit_int, 0) < 0) {
        return errno;
    }
    if (!WIFEXITED(exit_int)) {
        printf("Producer was unsuccessful.\n");
        return APR_EGENERAL;
    }
    printf("Waiting for consumer to exit.\n");
    if (waitpid(pidproducer, &exit_int, 0) < 0) {
        return errno;
    }
    if (!WIFEXITED(exit_int)) {
        printf("Consumer was unsuccessful.\n");
        return APR_EGENERAL;
    }

    printf("Destroying shared memory segment...");
    rv = apr_shm_destroy(shm);
    if (rv != APR_SUCCESS) {
        printf("FAILED\n");
        return rv;
    }
    printf("OK\n");

    apr_pool_destroy(pool);

    return APR_SUCCESS;
}
Пример #13
0
void ssl_scache_shmcb_init(server_rec *s, apr_pool_t *p)
{
    SSLModConfigRec *mc = myModConfig(s);
    void *shm_segment;
    apr_size_t shm_segsize;
    apr_status_t rv;
    SHMCBHeader *header;
    unsigned int num_subcache, num_idx, loop;

    /* Create shared memory segment */
    if (mc->szSessionCacheDataFile == NULL) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "SSLSessionCache required");
        ssl_die();
    }

    /* Use anonymous shm by default, fall back on name-based. */
    rv = apr_shm_create(&(mc->pSessionCacheDataMM), 
                        mc->nSessionCacheDataSize, 
                        NULL, mc->pPool);
    if (APR_STATUS_IS_ENOTIMPL(rv)) {
        /* For a name-based segment, remove it first in case of a
         * previous unclean shutdown. */
        apr_shm_remove(mc->szSessionCacheDataFile, mc->pPool);

        rv = apr_shm_create(&(mc->pSessionCacheDataMM),
                            mc->nSessionCacheDataSize,
                            mc->szSessionCacheDataFile,
                            mc->pPool);
    }

    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                     "could not allocate shared memory for shmcb "
                     "session cache");
        ssl_die();
    }

    shm_segment = apr_shm_baseaddr_get(mc->pSessionCacheDataMM);
    shm_segsize = apr_shm_size_get(mc->pSessionCacheDataMM);
    if (shm_segsize < (5 * sizeof(SHMCBHeader))) {
        /* the segment is ridiculously small, bail out */
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "shared memory segment too small");
        ssl_die();
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "shmcb_init allocated %" APR_SIZE_T_FMT
                 " bytes of shared memory",
                 shm_segsize);
    /* Discount the header */
    shm_segsize -= sizeof(SHMCBHeader);
    /* Select the number of subcaches to create and how many indexes each
     * should contain based on the size of the memory (the header has already
     * been subtracted). Typical non-client-auth sslv3/tlsv1 sessions are
     * around 150 bytes, so erring to division by 120 helps ensure we would
     * exhaust data storage before index storage (except sslv2, where it's
     * *slightly* the other way). From there, we select the number of subcaches
     * to be a power of two, such that the number of indexes per subcache at
     * least twice the number of subcaches. */
    num_idx = (shm_segsize) / 120;
    num_subcache = 256;
    while ((num_idx / num_subcache) < (2 * num_subcache))
        num_subcache /= 2;
    num_idx /= num_subcache;
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "for %" APR_SIZE_T_FMT " bytes (%" APR_SIZE_T_FMT 
                 " including header), recommending %u subcaches, "
                 "%u indexes each", shm_segsize,
                 shm_segsize + sizeof(SHMCBHeader), num_subcache, num_idx);
    if (num_idx < 5) {
        /* we're still too small, bail out */
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "shared memory segment too small");
        ssl_die();
    }
    /* OK, we're sorted */
    header = shm_segment;
    header->stat_stores = 0;
    header->stat_expiries = 0;
    header->stat_scrolled = 0;
    header->stat_retrieves_hit = 0;
    header->stat_retrieves_miss = 0;
    header->stat_removes_hit = 0;
    header->stat_removes_miss = 0;
    header->subcache_num = num_subcache;
    /* Convert the subcache size (in bytes) to a value that is suitable for
     * structure alignment on the host platform, by rounding down if necessary.
     * This assumes that sizeof(unsigned long) provides an appropriate
     * alignment unit.  */
    header->subcache_size = ((size_t)(shm_segsize / num_subcache) &
                             ~(size_t)(sizeof(unsigned long) - 1));
    header->subcache_data_offset = sizeof(SHMCBSubcache) +
                                   num_idx * sizeof(SHMCBIndex);
    header->subcache_data_size = header->subcache_size -
                                 header->subcache_data_offset;
    header->index_num = num_idx;

    /* Output trace info */
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "shmcb_init_memory choices follow");
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "subcache_num = %u", header->subcache_num);
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "subcache_size = %u", header->subcache_size);
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "subcache_data_offset = %u", header->subcache_data_offset);
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "subcache_data_size = %u", header->subcache_data_size);
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "index_num = %u", header->index_num);
    /* The header is done, make the caches empty */
    for (loop = 0; loop < header->subcache_num; loop++) {
        SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop);
        subcache->idx_pos = subcache->idx_used = 0;
        subcache->data_pos = subcache->data_used = 0;
    }
    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
                 "Shared memory session cache initialised");
    /* Success ... */
    mc->tSessionCacheDataTable = shm_segment;
}