예제 #1
0
파일: yrmcds.c 프로젝트: cybozu/php-yrmcds
/* Resource destructors. */
static void destruct_conn(php_yrmcds_t* c) {
    c->reference_count -= 1;

    if( c->pkey ) {
        uint32_t serial;
        yrmcds_set_timeout(&c->res, (int)YRMCDS_G(default_timeout));
        int e = yrmcds_unlockall(&c->res, 0, &serial);
        if( e != YRMCDS_OK ) {
            on_broken_connection_detected(c, e, YRMCDS_STATUS_OK);
            return;
        }
        yrmcds_response r;
        do {
            e = yrmcds_recv(&c->res, &r);
            if( e != YRMCDS_OK ) {
                on_broken_connection_detected(c, e, YRMCDS_STATUS_OK);
                return;
            }
        } while( r.serial != serial );
        if( r.status != YRMCDS_STATUS_OK &&
            // memcached does not support locking, so
            r.status != YRMCDS_STATUS_UNKNOWNCOMMAND ) {
            on_broken_connection_detected(c, e, r.status);
            return;
        }
        return;
    }

    // Since `c` does not use persistent connection,
    // the resources of `c` is not shared with other clients.
    // Therefore, we can clean up resources here.
    yrmcds_close(&c->res);
    efree(c);
}
예제 #2
0
파일: yrmcds.c 프로젝트: cybozu/php-yrmcds
static ZEND_RSRC_DTOR_FUNC(php_yrmcds_resource_pdtor) {
    if( res->ptr == NULL )
        return;
    php_yrmcds_t* c = (php_yrmcds_t*)res->ptr;
    if( c->reference_count != 0 ) {
        char buf[256];
        snprintf(buf, sizeof(buf), "yrmcds: non-zero reference_count on pdtor: %zu", c->reference_count);
        php_log_err(buf);
    }

    yrmcds_close(&c->res);
    pefree((void*)c->pkey, 1);
    pefree(c, 1);
    res->ptr = NULL;
}
예제 #3
0
파일: yc.c 프로젝트: cybozu/php-yrmcds
int main(int argc, char** argv) {
    const char* server = DEFAULT_SERVER;
    uint16_t port = DEFAULT_PORT;
    size_t compression = DEFAULT_COMPRESS;

    while( 1 ) {
        int n;
        int c = getopt(argc, argv, "s:p:c:dqvh");
        if( c == -1 ) break;
        switch( c ) {
        case 's':
            server = optarg;
            break;
        case 'p':
            n = atoi(optarg);
            if( n <= 0 || n > 65535 ) {
                fprintf(stderr, "Invalid TCP port.\n");
                return 1;
            }
            port = (uint16_t)n;
            break;
        case 'c':
            n = atoi(optarg);
            if( n <= 0 ) {
                fprintf(stderr, "Invalid compression thoreshold.\n");
                return 1;
            }
            compression = (size_t)n;
            break;
        case 'd':
            debug = 1;
            break;
        case 'q':
            quiet = 1;
            break;
        case 'v':
            version();
            return 0;
        case 'h':
            usage();
            return 0;
        default:
            return 1;
        }
    }

    if( optind == argc ) {
        usage();
        return 0;
    }

    const char* cmd = argv[optind];
    argc -= optind + 1;
    argv += optind + 1;

    yrmcds s[1];
    yrmcds_error e = yrmcds_connect(s, server, port);
    CHECK_ERROR(e);
    e = yrmcds_set_compression(s, compression);
    if( e != 0 && e != YRMCDS_NOT_IMPLEMENTED ) {
        yrmcds_close(s);
        CHECK_ERROR(e);
    }

    int ret = 1;
#define do_cmd(name)                            \
    if( strcmp(cmd, #name) == 0 )  {            \
        ret = cmd_##name(argc, argv, s);        \
            goto OUT;                           \
    }

    do_cmd(noop);
    do_cmd(get);
    do_cmd(getk);
    do_cmd(gat);
    do_cmd(gatk);
    do_cmd(lag);
    do_cmd(lagk);
    do_cmd(touch);
    do_cmd(set);
    do_cmd(replace);
    do_cmd(add);
    do_cmd(rau);
    do_cmd(incr);
    do_cmd(decr);
    do_cmd(append);
    do_cmd(prepend);
    do_cmd(delete);
    do_cmd(lock);
    do_cmd(unlock);
    do_cmd(unlockall);
    do_cmd(flush);
    do_cmd(stat);
    do_cmd(keys);
    do_cmd(version);
    do_cmd(quit);

    fprintf(stderr, "No such command: %s\n", cmd);

  OUT:
    yrmcds_close(s);
    return ret;
}
예제 #4
0
파일: memcached.c 프로젝트: Handy2015/h2o
static void reader_main(h2o_memcached_context_t *ctx)
{
    struct st_h2o_memcached_conn_t conn = {ctx, {}, PTHREAD_MUTEX_INITIALIZER, {&conn.inflight, &conn.inflight}, 0};
    pthread_t writer_thread;
    yrmcds_response resp;
    yrmcds_error err;

    /* connect to server and start the writer thread */
    connect_to_server(conn.ctx, &conn.yrmcds);
    pthread_create(&writer_thread, NULL, writer_main, &conn);

    pthread_mutex_lock(&conn.ctx->mutex);
    ++conn.ctx->num_threads_connected;
    pthread_mutex_unlock(&conn.ctx->mutex);

    /* receive data until an error occurs */
    while (1) {
        if ((err = yrmcds_recv(&conn.yrmcds, &resp)) != YRMCDS_OK) {
            fprintf(stderr, "[lib/common/memcached.c] yrmcds_recv:%s\n", yrmcds_strerror(err));
            break;
        }
        h2o_memcached_req_t *req = pop_inflight(&conn, resp.serial);
        if (req == NULL) {
            fprintf(stderr, "[lib/common/memcached.c] received unexpected serial\n");
            break;
        }
        if (resp.status == YRMCDS_STATUS_OK) {
            req->data.get.value = h2o_iovec_init(h2o_mem_alloc(resp.data_len), resp.data_len);
            memcpy(req->data.get.value.base, resp.data, resp.data_len);
            h2o_mem_set_secure((void *)resp.data, 0, resp.data_len);
        }
        h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
    }

    /* send error to all the reqs in-flight */
    pthread_mutex_lock(&conn.mutex);
    while (!h2o_linklist_is_empty(&conn.inflight)) {
        h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, inflight, conn.inflight.next);
        h2o_linklist_unlink(&req->inflight);
        assert(req->type == REQ_TYPE_GET);
        h2o_multithread_send_message(req->data.get.receiver, &req->data.get.message);
    }
    pthread_mutex_unlock(&conn.mutex);

    /* stop the writer thread */
    __sync_add_and_fetch(&conn.writer_exit_requested, 1);
    pthread_mutex_lock(&conn.ctx->mutex);
    pthread_cond_broadcast(&conn.ctx->cond);
    pthread_mutex_unlock(&conn.ctx->mutex);
    pthread_join(writer_thread, NULL);

    /* decrement num_threads_connected, and discard all the pending requests if no connections are alive */
    pthread_mutex_lock(&conn.ctx->mutex);
    if (--conn.ctx->num_threads_connected == 0) {
        while (!h2o_linklist_is_empty(&conn.ctx->pending)) {
            h2o_memcached_req_t *req = H2O_STRUCT_FROM_MEMBER(h2o_memcached_req_t, pending, conn.ctx->pending.next);
            h2o_linklist_unlink(&req->pending);
            discard_req(req);
        }
    }
    pthread_mutex_unlock(&conn.ctx->mutex);

    /* close the connection */
    yrmcds_close(&conn.yrmcds);
}