static int do_shm_open()

in native/common/jk_shm.c [529:716]


static int do_shm_open(const char *fname, int attached,
                       int sz, jk_log_context_t *l)
{
    int rc;
    int fd;
    void *base;
#ifdef AS400_UTF8
    char *wptr;
#endif

    JK_TRACE_ENTER(l);
    if (!jk_shm_inited_cs) {
        jk_shm_inited_cs = 1;
        JK_INIT_CS(&jk_shmem.cs, rc);
    }
    if (jk_shmem.hdr) {
        /* Probably a call from vhost */
        if (!attached)
            attached = 1;
    }
    else if (attached) {
        /* We should already have a header
         * Use memory if we don't
         */
        JK_TRACE_EXIT(l);
        return 0;
    }
    if (sz < 0) {
        jk_log(l, JK_LOG_ERROR, "Invalid shared memory size (%d)", sz);
        JK_TRACE_EXIT(l);
        return EINVAL;
    }
    jk_shmem.size = JK_SHM_ALIGN(JK_SHM_SLOT_SIZE + sz);

    if (!fname) {
        /* Use plain memory in case there is no file name */
        if (!jk_shmem.filename)
            jk_shmem.filename  = strdup("memory");
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "Using process memory as shared memory");
        JK_TRACE_EXIT(l);
        return 0;
    }

    if (!jk_shmem.filename) {
        jk_shmem.filename = (char *)malloc(strlen(fname) + 32);
        sprintf(jk_shmem.filename, "%s.%" JK_PID_T_FMT, fname, getpid());
    }
    if (!attached) {
        size_t size;
        jk_shmem.attached = 0;
#ifdef AS400_UTF8
        wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
        jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
        fd = open(wptr, O_RDWR|O_CREAT|O_TRUNC, 0600);
        free(wptr);
#else
        fd = open(jk_shmem.filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
#endif
        if (fd == -1) {
            jk_shmem.size = 0;
            JK_TRACE_EXIT(l);
            return errno;
        }
        size = lseek(fd, 0, SEEK_END);
        if (size < jk_shmem.size) {
            size = jk_shmem.size;
            if (ftruncate(fd, jk_shmem.size)) {
                rc = errno;
                close(fd);
#ifdef  AS400_UTF8
                wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
                jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
                unlink(wptr);
                free(wptr);
#else
                unlink(jk_shmem.filename);
#endif
                jk_shmem.size = 0;
                JK_TRACE_EXIT(l);
                return rc;
            }
            if (JK_IS_DEBUG_LEVEL(l))
                jk_log(l, JK_LOG_DEBUG,
                       "Truncated shared memory to %u", size);
        }
        if (lseek(fd, 0, SEEK_SET) != 0) {
            rc = errno;
            close(fd);
#ifdef  AS400_UTF8
            wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
            jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
            unlink(wptr);
            free(wptr);
#else
            unlink(jk_shmem.filename);
#endif
            jk_shmem.size = 0;
            JK_TRACE_EXIT(l);
            return rc;
        }

        base = mmap((caddr_t)0, jk_shmem.size,
                    PROT_READ | PROT_WRITE,
                    MAP_FILE | MAP_SHARED,
                    fd, 0);
        if (base == (caddr_t)MAP_FAILED || base == (caddr_t)0) {
            rc = errno;
            close(fd);
#ifdef  AS400_UTF8
            wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
            jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
            unlink(wptr);
            free(wptr);
#else
            unlink(jk_shmem.filename);
#endif
            jk_shmem.size = 0;
            JK_TRACE_EXIT(l);
            return rc;
        }
        jk_shmem.hdr = base;
        jk_shmem.fd  = fd;
        memset(jk_shmem.hdr, 0, jk_shmem.size);
        memcpy(jk_shmem.hdr->h.data.magic, shm_signature, JK_SHM_MAGIC_SIZ);
        jk_shmem.hdr->h.data.size = sz;
        jk_shmem.hdr->h.data.childs = 1;
        jk_shmem.hdr->h.data.maintain_checking = 0;
        jk_shmem.hdr->h.data.maintain_time = time(NULL);
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "Initialized shared memory %s size=%u free=%u addr=%#lx",
                   jk_shm_name(), jk_shmem.size,
                   jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
                   jk_shmem.hdr);
    }
    else {
        jk_shmem.hdr->h.data.childs++;
        jk_shmem.attached = (int)getpid();
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "Attached shared memory %s [%d] size=%u workers=%u free=%u addr=%#lx",
                   jk_shm_name(),
                   jk_shmem.hdr->h.data.childs,
                   jk_shmem.size, jk_shmem.hdr->h.data.workers - 1,
                   jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
                   jk_shmem.hdr);
#if 0
        /*
         * Reset the shared memory so that
         * alloc works even for attached memory.
         * XXX: This might break already used memory
         * if the number of workers change between
         * open and attach or between two attach operations.
         */
        if (nchild > 1) {
            if (JK_IS_DEBUG_LEVEL(l)) {
                jk_log(l, JK_LOG_DEBUG,
                       "Resetting the shared memory for child %d",
                       nchild);
            }
        }
        jk_shmem.hdr->h.data.pos     = 0;
        jk_shmem.hdr->h.data.workers = 0;
#endif
    }
    if ((rc = do_shm_open_lock(jk_shmem.filename, attached, l))) {
        if (!attached) {
            munmap((void *)jk_shmem.hdr, jk_shmem.size);
            close(jk_shmem.fd);
#ifdef  AS400_UTF8
            wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
            jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
            unlink(wptr);
            free(wptr);
#else
            unlink(jk_shmem.filename);
#endif
        }
        jk_shmem.hdr = NULL;
        jk_shmem.fd  = -1;
        JK_TRACE_EXIT(l);
        return rc;
    }
    JK_TRACE_EXIT(l);
    return 0;
}