Ejemplo n.º 1
0
pc_hash_t *pc_hash_create_min(pc_pool_t *pool, int min_items)
{
    pc_hash_t *result = pc_alloc(pool, sizeof(*result));

    result->count = 0;
    result->pool = pool;

    if (min_items > 1000000000)
        result->twins_index = TWINS_COUNT - 1;
    else
    {
        /* Scale up MIN_ITEMS based on our desired initial load factor  */
        if (min_items > 10000000)
        {
            min_items = (min_items / INITIAL_LOAD) * 100;
            result->twins_index = TWIN_MIN_10MIL;
        }
        else
        {
            min_items = (min_items * 100) / INITIAL_LOAD;
            result->twins_index = 0;
        }

        while (twins[result->twins_index] < min_items
               && result->twins_index < TWINS_COUNT - 1)
            ++result->twins_index;
    }

    result->alloc = twins[result->twins_index] + 2;  /* higher of the pair!  */
    result->slots = pc_alloc(pool, result->alloc * sizeof(*result->slots));
    pc_hash_clear(result);

    return result;
}
Ejemplo n.º 2
0
static void
maybe_grow(pc_hash_t *hash)
{
    int threshold;
    int alloc;
    struct pc_hslot_s *slots;

    if (hash->twins_index == TWINS_COUNT - 1)
        return;

    if (hash->alloc < 10000000)
        threshold = (hash->alloc * MAX_LOAD_PERCENT) / 100;
    else
        threshold = (hash->alloc / 100) * MAX_LOAD_PERCENT;

    if (hash->count + 1 < threshold)
        return;

    alloc = twins[++hash->twins_index] + 2;  /* the higher of the pair!  */
    slots = pc_alloc(hash->pool, alloc * sizeof(*slots));
    memset(slots, 0, alloc * sizeof(*slots));

    copy_items(hash, slots, alloc);

    /* ### free old hash->slots  */
    hash->alloc = alloc;
    hash->slots = slots;
}
Ejemplo n.º 3
0
pc_hiter_t *pc_hiter_begin(const pc_hash_t *hash, pc_pool_t *pool)
{
    pc_hiter_t *result = pc_alloc(pool, sizeof(*result));

    result->current = hash->slots;
    result->last = &hash->slots[hash->alloc];
    if (result->current->key == NULL || result->current->key == SLOT_DELETED)
        return pc_hiter_next(result);
    return result;
}
Ejemplo n.º 4
0
pc_error_t *pc_address_lookup(pc_hash_t **addresses,
                              const char *name,
                              int port,
                              int flags,
                              pc_pool_t *pool)
{
    char portbuf[6];
    struct addrinfo hints = { 0 };
    struct addrinfo *results;
    struct addrinfo *scan;
    int rv;

    if (port <= 0 || port > 65535)
        return pc_error_create_pm(pool, PC_ERR_BAD_PARAM,
                                  "port number out of range");
    snprintf(portbuf, sizeof(portbuf), "%d", port);

    /* ### these are the wrong hints for now, but let's just get started  */
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    rv = getaddrinfo(name, portbuf, &hints, &results);
    if (rv != 0)
    {
        const char *msg = gai_strerror(rv);

        return pc_error_create_pm(pool, PC_ERR_ADDRESS_LOOKUP, msg);
    }

    *addresses = pc_hash_create(pool);
    for (scan = results; scan != NULL; scan = scan->ai_next)
    {
        /* Can the returned address fit into our structure?
           ### this is probably bogus and needs some research.  */
        if (scan->ai_addrlen <= sizeof(((pc_address_t *)0)->a.inet))
        {
            pc_address_t *addr = pc_alloc(pool, sizeof(*addr));
            const char *readable;

            memcpy(&addr->a.inet, scan->ai_addr, scan->ai_addrlen);

            readable = pc_address_readable(addr, pool);
            pc_hash_sets(*addresses, readable, addr);
        }
    }

    freeaddrinfo(results);

    return PC_NO_ERROR;
}
Ejemplo n.º 5
0
static read_buffer_t *
get_read_buffer(struct pc__channel_ctx_s *cctx)
{
    read_buffer_t *rb = cctx->avail;

    if (rb == NULL)
    {
        rb = pc_alloc(cctx->pool, sizeof(*rb) + READ_BUFFER_SIZE);
        rb->buf = (char *)rb + sizeof(*rb);
        rb->len = READ_BUFFER_SIZE;

        return rb;
    }

    cctx->avail = rb->next;
    return rb;
}
Ejemplo n.º 6
0
static void
get_iovec(struct iovec **result_iov,
          int *result_iovcnt,
          pc_channel_t *channel)
{
    int iovcnt = channel->pending_iovcnt;
    char *buf = channel->pending_buf;

    assert(channel->pending_iov != NULL && iovcnt > 0);

    /* The simplest case: we can directly use PENDING_IOV because we don't
       need to adjust the first iovec for PENDING_BUF.  */
    if (buf == NULL || buf == channel->pending_iov[0].iov_base)
    {
        *result_iov = channel->pending_iov;
        *result_iovcnt = iovcnt;
        return;
    }

    /* The first iovec must be adjusted, so we need to copy it into our
       pre-allocated scratch area, or onto the heap.  */

    if (iovcnt <= INTERNAL_IOVEC_COUNT)
    {
        *result_iov = &channel->ctx->cctx->scratch_iov[0];
        *result_iovcnt = iovcnt;
    }
    else
    {
        *result_iov = pc_alloc(channel->ctx->cctx->callback_scratch,
                               iovcnt * sizeof(**result_iov));
        *result_iovcnt = iovcnt;
    }

    memcpy(*result_iov, channel->pending_iov, iovcnt * sizeof(**result_iov));
    (*result_iov)[0].iov_base = buf;
    (*result_iov)[0].iov_len =
        (channel->pending_iov[0].iov_len
         - (buf - (char *)channel->pending_iov[0].iov_base));
}