예제 #1
0
파일: enm_drv.c 프로젝트: basho/enm
static int
enm_do_send(EnmData* d, const struct nn_msghdr* msghdr, int* err)
{
    int rc;

    if (msghdr->msg_iovlen == 0)
        return 0;
    *err = 0;
    do {
        rc = nn_sendmsg(d->fd, msghdr, NN_DONTWAIT);
        if (rc < 0) {
            *err = errno;
            switch (*err) {
            case EINTR:
            case EFSM:
                /* do nothing */
                break;
            case EAGAIN:
                d->b.writable = 0;
                break;
            default:
                enm_write_select(d, 0);
                enm_read_select(d, 0);
                driver_failure(d->port, *err);
            }
        }
    } while (*err == EINTR);
    return rc;
}
예제 #2
0
static void failure_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
    FailureDrvData *data_p = (FailureDrvData *) drv_data;
    void *void_ptr;
    ErlDrvPort port = void_ptr = data_p;

#ifdef __WIN32__
    Sleep(3000);
#else
    sleep(3);
#endif
    driver_failure(port, 0);
}
예제 #3
0
파일: enm_drv.c 프로젝트: basho/enm
static void
enm_outputv(ErlDrvData drv_data, ErlIOVec *ev)
{
    EnmData* d = (EnmData*)drv_data;
    ErlIOVec qev;
    ErlDrvSizeT qtotal;
    struct nn_msghdr msghdr;
    int i, rc = -1, err;

    if (d->fd == -1 || d->protocol == NN_PULL || d->protocol == NN_SUB)
        return;
    qtotal = driver_peekqv(d->port, &qev);
    if (qtotal > 0) {
        memset(&msghdr, 0, sizeof msghdr);
        msghdr.msg_iov = (struct nn_iovec*)qev.iov;
        msghdr.msg_iovlen = qev.vsize;
        msghdr.msg_control = 0;
        err = 0;
        do {
            rc = enm_do_send(d, &msghdr, &err);
            if (rc < 0) {
                if (err == EAGAIN) {
                    d->b.writable = 0;
                    break;
                } else if (err != EINTR) {
                    char errstr[32];
                    switch (enm_errno_str(err, errstr)) {
                    case ENM_NANOMSG_ERROR:
                        driver_failure_atom(d->port, errstr);
                        break;
                    case ENM_POSIX_ERROR:
                        driver_failure_posix(d->port, err);
                        break;
                    case ENM_UNKNOWN_ERROR:
                        driver_failure(d->port, err);
                        break;
                    }
                    return;
                }
            }
        } while (err == EINTR);
    }
    /*
     * Do nothing if the message has no data
     */
    if (ev->size == 0 || ev->vsize == 0 ||
        (ev->vsize == 1 && *ev->binv == 0 && ev->iov->iov_len == 0))
        return;
    if (d->b.writable) {
        memset(&msghdr, 0, sizeof msghdr);
        msghdr.msg_iov = (struct nn_iovec*)ev->iov;
        msghdr.msg_iovlen = ev->vsize;
        msghdr.msg_control = 0;
        err = 0;
        do {
            rc = enm_do_send(d, &msghdr, &err);
            if (rc < 0) {
                if (err == EAGAIN) {
                    d->b.writable = 0;
                    break;
                } else if (err != EINTR) {
                    char errstr[32];
                    switch (enm_errno_str(err, errstr)) {
                    case ENM_NANOMSG_ERROR:
                        driver_failure_atom(d->port, errstr);
                        break;
                    case ENM_POSIX_ERROR:
                        driver_failure_posix(d->port, err);
                        break;
                    case ENM_UNKNOWN_ERROR:
                        driver_failure(d->port, err);
                        break;
                    }
                    return;
                }
            }
        } while (err == EINTR);
    }
    if (rc < 0 && !d->b.writable) {
        rc = 0;
        d->b.busy = 1;
        set_busy_port(d->port, d->b.busy);
        for (i = 0; i < ev->vsize; i++) {
            ErlDrvBinary* bin = 0;
            if (ev->binv[i] != 0) {
                bin = ev->binv[i];
                driver_binary_inc_refc(bin);
            } else if (ev->iov[i].iov_len > 0) {
                SysIOVec* vec = &ev->iov[i];
                bin = driver_alloc_binary(vec->iov_len);
                memcpy(bin->orig_bytes, vec->iov_base, vec->iov_len);
            }
            if (bin != 0)
                driver_enq_bin(d->port, bin, 0, bin->orig_size);
        }
        if (!d->b.write_poll)
            enm_write_select(d, 1);
    }
    if (rc > 0 && d->protocol == NN_SURVEYOR && d->b.active != ENM_FALSE)
        enm_read_select(d, 1);
}
예제 #4
0
파일: echo_drv.c 프로젝트: aesedepece/otp
static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
    EchoDrvData* data_p = (EchoDrvData *) drv_data;
    ErlDrvPort port = data_p->erlang_port;

    switch (buf[0]) {
    case ECHO_DRV_OUTPUT:
    {
        driver_output(port, buf+1, len-1);
        break;
    }
    case ECHO_DRV_OUTPUT2:
    {
         driver_output2(port, "a", 1, buf+1, len-1);
         break;
    }
    case ECHO_DRV_OUTPUT_BINARY:
    {
        ErlDrvBinary *bin = driver_alloc_binary(len-1);
        memcpy(&bin->orig_bytes, buf+1, len-1);
        driver_output_binary(port, "a", 1, bin, 1, len - 2);
        driver_free_binary(bin);
        break;
    }
    case ECHO_DRV_OUTPUTV:
    {
        ErlIOVec iov;
        ErlDrvSizeT sz;
        driver_enq(port, buf + 1, len - 1);
        sz = driver_peekqv(port, &iov);
        driver_outputv(port, "a", 1, &iov, 0);
        driver_deq(port, sz);
        break;
    }
    case ECHO_DRV_SET_TIMER:
    {
        driver_set_timer(port, 10);
        break;
    }
    case ECHO_DRV_FAILURE_EOF:
    {
        driver_failure_eof(port);
        break;
    }
    case ECHO_DRV_FAILURE_ATOM:
    {
        driver_failure_atom(port, buf+1);
        break;
    }
    case ECHO_DRV_FAILURE_POSIX:
    {
        driver_failure_posix(port, EAGAIN);
        break;
    }
    case ECHO_DRV_FAILURE:
    {
        driver_failure(port, buf[1]);
        break;
    }
    case ECHO_DRV_OUTPUT_TERM:
    case ECHO_DRV_DRIVER_OUTPUT_TERM:
    case ECHO_DRV_SEND_TERM:
    case ECHO_DRV_DRIVER_SEND_TERM:
    {
        ErlDrvTermData term[] = {
            ERL_DRV_ATOM, driver_mk_atom("echo"),
            ERL_DRV_PORT, driver_mk_port(port),
            ERL_DRV_BUF2BINARY, (ErlDrvTermData)(buf+1),
                                (ErlDrvTermData)(len - 1),
            ERL_DRV_TUPLE, 3};
        switch (buf[0]) {
        case ECHO_DRV_OUTPUT_TERM:
            erl_drv_output_term(driver_mk_port(port), term, sizeof(term) / sizeof(ErlDrvTermData));
            break;
        case ECHO_DRV_DRIVER_OUTPUT_TERM:
            driver_output_term(port, term, sizeof(term) / sizeof(ErlDrvTermData));
            break;
        case ECHO_DRV_SEND_TERM:
            driver_send_term(port, data_p->caller,
                             term, sizeof(term) / sizeof(ErlDrvTermData));
            break;
        case ECHO_DRV_DRIVER_SEND_TERM:
            erl_drv_send_term(driver_mk_port(port), data_p->caller,
                              term, sizeof(term) / sizeof(ErlDrvTermData));
            break;
        }
        break;
    }
    case ECHO_DRV_SAVE_CALLER:
        data_p->caller = driver_caller(port);
        break;
    default:
        break;
    }
}