/*start select()ing on a socket*/
static int
update_event(lcb_io_opt_t cbcio, lcb_socket_t sock, void *event, short flags,
    void *cb_data, lcb_ioE_callback handler)
{
    plcb_IOPROCS *object;
    plcb_EVENT *cevent;
    
    cevent = (plcb_EVENT*)event;
    object = (plcb_IOPROCS*)(cbcio->v.v0.cookie);

    if (cevent->flags == flags &&
            cevent->lcb_handler == handler &&
            cevent->lcb_arg == cb_data) {

        return 0;
    }

    /*these are set in the AV after the call to Perl*/
    cevent->fd = sock;
    cevent->lcb_handler = handler;
    cevent->lcb_arg = cb_data;

    modify_event_perl(object, cevent, flags);
    return 0;
}
/*start select()ing on a socket*/
static int update_event(plcba_cbcio *cbcio,
                        lcb_socket_t sock,
                        void *event,
                        short flags,
                        void *cb_data,
                        plcba_c_evhandler handler)
{
    PLCBA_t *object;
    PLCBA_c_event *cevent;
    PLCBA_evaction_t action;
    PLCBA_evstate_t new_state;
    
    cevent = (PLCBA_c_event*)event;
    object = (PLCBA_t*)(cbcio->v.v0.cookie);
    
    if (!flags) {
        action = PLCBA_EVACTION_UNWATCH;
        new_state = PLCBA_EVSTATE_INITIALIZED;

    } else {
        action = PLCBA_EVACTION_WATCH;
        new_state = PLCBA_EVSTATE_ACTIVE;
    }

    
    if (cevent->flags == flags &&
       cevent->c.handler == handler &&
       cevent->c.arg == cb_data &&
       new_state == cevent->state) {
        /*nothing to do here*/
        return 0;
    }
    
    /*these are set in the AV after the call to Perl*/
    cevent->fd = sock;
    cevent->flags = flags;
    cevent->c.handler = handler;
    cevent->c.arg = cb_data;
    
    modify_event_perl(object, cevent, action, flags);
    return 0;
}
/*
 we use this to tell the event system that pending operations have been
 completed.
 this is mainly useful for things like connect().
 
 Apparently we need to make sure libcouchbase also does not actually receive
 events here either, or things become inconsistent.
 
*/
static void stop_event_loop(plcba_cbcio *cbcio)
{
    PLCBA_t *async;
    PLCBA_c_event *cevent;
    dSP;

    async = cbcio->v.v0.cookie;
    
    for (cevent = async->cevents; cevent; cevent = cevent->next) {

        if (cevent->evtype == PLCBA_EVTYPE_IO && cevent->fd > 0) {
            cevent->state = PLCBA_EVSTATE_SUSPENDED;
            modify_event_perl(async, cevent, PLCBA_EVACTION_SUSPEND, -1);
        }
    }
    
    //warn("Calling cv_waitdone");
    PUSHMARK(SP);
    call_sv(async->cv_waitdone, G_DISCARD|G_NOARGS);
}
/*We need to resume watching on all events here*/
static void run_event_loop(plcba_cbcio *cbcio)
{
    PLCBA_t *async;
    PLCBA_c_event *cevent;
    
    async = (PLCBA_t*)cbcio->v.v0.cookie;
    
    //warn("Resuming events..");
    for (cevent = async->cevents; cevent; cevent = cevent->next) {

        if (cevent->evtype == PLCBA_EVTYPE_IO && cevent->fd > 0) {
            cevent->state = PLCBA_EVSTATE_ACTIVE;
            modify_event_perl(async,
                              cevent,
                              PLCBA_EVACTION_RESUME,
                              cevent->flags);
        }
    }
    
    //warn("Running event loop...");
}