예제 #1
0
파일: ae.c 프로젝트: 290420058/kids
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
        aeFileProc *proc, void *clientData)
{
    if (fd >= eventLoop->setsize) {
        errno = ERANGE;
        return AE_ERR;
    }
    aeFileEvent *fe = &eventLoop->events[fd];

    if (aeApiAddEvent(eventLoop, fd, mask) == -1)
        return AE_ERR;
    fe->mask |= mask;
    if (mask & AE_READABLE) fe->rfileProc = proc;
    if (mask & AE_WRITABLE) fe->wfileProc = proc;
    fe->clientData = clientData;
    if (fd > eventLoop->maxfd)
        eventLoop->maxfd = fd;
    return AE_OK;
}
예제 #2
0
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData)
{
    aeFileEvent *fe = NULL;

    if(fd >= eventLoop->setsize){
        return (-1);
    }
    
    fe = &eventLoop->events[fd];

    if(aeApiAddEvent(eventLoop, fd, mask)==-1){
        return (-1);
    }
    fe->mask |= mask;
    if(mask & AE_READABLE) fe->rfileProc = proc;
    if(mask & AE_WRITABLE) fe->wfileProc = proc;
    fe->clientData = clientData;
    if(fd > eventLoop->maxfd) eventLoop->maxfd = fd;

    return 0;
}
예제 #3
0
/*
* 根据 mask 参数的值,监听 fd 文件的状态,
* 当 fd 可用时,执行 proc 函数
*/
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
                      aeFileProc *proc, void *clientData)
{
    if (fd >= eventLoop->setsize) return AE_ERR;
    aeFileEvent *fe = &eventLoop->events[fd];

    // 监听指定 fd
    if (aeApiAddEvent(eventLoop, fd, mask) == -1)
        return AE_ERR;

    // 设置文件事件类型
    fe->mask |= mask;
    if (mask & AE_READABLE) fe->rfileProc = proc;
    if (mask & AE_WRITABLE) fe->wfileProc = proc;

    fe->clientData = clientData;

    // 如果有需要,更新事件处理器的最大 fd
    if (fd > eventLoop->maxfd)
        eventLoop->maxfd = fd;

    return AE_OK;
}
예제 #4
0
파일: ae.c 프로젝트: ymsdu2004/redis-2.8.14
/***
 * 创建IO事件并注册IO事件
 * @eventLoop[IN]: 新建事件要添加到的事件循环处理器
 * @fd[IN]: IO事件对应的文件描述符
 * @mask[IN]: IO事件关注的事件类型, AE_READABLE与AE_WRITEABLE的任意结合
 * @proc[IN]: IO事件就绪处理函数, 这里读和写事件公用一个处理函数, 可以根据处理函数传入的mask区分
 * @clientData[IN]: 用户私有数据, 事件处理函数调用时传回
 * @return: 成功返回AE_OK, 失败返回AE_ERR
 */
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
        aeFileProc *proc, void *clientData)
{
	/* 如果要注册的IO事件对应的文件描述符不小于setsize, 则返回失败 */
    if (fd >= eventLoop->setsize) {
        errno = ERANGE;
        return AE_ERR;
    }
	
	/* 根据fd定位到已注册IO事件数组中相应的event元素 */
    aeFileEvent *fe = &eventLoop->events[fd];

	/* 将fd注册到操作系统特定IO复用设施中 */
    if (aeApiAddEvent(eventLoop, fd, mask) == -1)
        return AE_ERR;
		
	/* 以下部分填充fd在数组中对应的event结构体 */
	
	/* 填充mask标记 */
    fe->mask |= mask;
	
	/* 如果关注读事件, 则设置读就绪处理函数 */
    if (mask & AE_READABLE) fe->rfileProc = proc;
	
	/* 如果关注些事件, 则设置写就绪处理函数 */
    if (mask & AE_WRITABLE) fe->wfileProc = proc;
	
	/* 记录用户私有数据 */
    fe->clientData = clientData;
	
	/* 如果新注册的IO事件的fd值大于eventLoop中的maxfd, 则以fd更新maxfd */
    if (fd > eventLoop->maxfd)
        eventLoop->maxfd = fd;
		
    return AE_OK;
}
예제 #5
0
파일: ae_wsiocp.c 프로젝트: bugou/test
/* return array of sockets that are ready for read or write 
   depending on the mask for each socket */
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
    aeApiState *state = (aeApiState *)eventLoop->apidata;
    aeSockState *sockstate;
    ULONG j;
    int numevents = 0;
    ULONG numComplete = 0;
    int rc;
	int mswait = (tvp == NULL) ? 100 : (tvp->tv_sec * 1000) + (tvp->tv_usec / 1000);

    if (pGetQueuedCompletionStatusEx != NULL) {
        /* first get an array of completion notifications */
        rc = pGetQueuedCompletionStatusEx(state->iocp,
                                        state->entries,
                                        MAX_COMPLETE_PER_POLL,
                                        &numComplete,
                                        mswait,
                                        FALSE);
    } else {
        /* need to get one at a time. Use first array element */
        rc = GetQueuedCompletionStatus(state->iocp,
                                        &state->entries[0].dwNumberOfBytesTransferred,
                                        &state->entries[0].lpCompletionKey,
                                        &state->entries[0].lpOverlapped,
                                        mswait);
        if (!rc && state->entries[0].lpOverlapped == NULL) {
            // timeout. Return.
            return 0;
        } else {
            // check if more completions are ready
            int lrc = 1;
            rc = 1;
            numComplete = 1;

            while (numComplete < MAX_COMPLETE_PER_POLL) {
                lrc = GetQueuedCompletionStatus(state->iocp,
                                                &state->entries[numComplete].dwNumberOfBytesTransferred,
                                                &state->entries[numComplete].lpCompletionKey,
                                                &state->entries[numComplete].lpOverlapped,
                                                0);
                if (lrc) {
                   numComplete++;
                } else {
                    if (state->entries[numComplete].lpOverlapped == NULL) break;
                }
            }
        }
    }

    if (rc && numComplete > 0) {
        LPOVERLAPPED_ENTRY entry = state->entries;
        for (j = 0; j < numComplete && numevents < state->setsize; j++, entry++) {
            /* the competion key is the socket */
            int rfd = (int)entry->lpCompletionKey;
            sockstate = aeGetExistingSockState(state, rfd);

            if (sockstate != NULL) {
                if ((sockstate->masks & LISTEN_SOCK) && entry->lpOverlapped != NULL) {
                    /* need to set event for listening */
                    aacceptreq *areq = (aacceptreq *)entry->lpOverlapped;
                    areq->next = sockstate->reqs;
                    sockstate->reqs = areq;
                    sockstate->masks &= ~ACCEPT_PENDING;
                    if (sockstate->masks & AE_READABLE) {
                        eventLoop->fired[numevents].fd = rfd;
                        eventLoop->fired[numevents].mask = AE_READABLE;
                        numevents++;
                    }
                } else if (sockstate->masks & CONNECT_PENDING) {
                    /* check if connect complete */
                    if (entry->lpOverlapped == &sockstate->ov_read) {
                        sockstate->masks &= ~CONNECT_PENDING;
                        /* enable read and write events for this connection */
                        aeApiAddEvent(eventLoop, rfd, sockstate->masks);
                    }
                } else {
                    int matched = 0;
                    /* check if event is read complete (may be 0 length read) */
                    if (entry->lpOverlapped == &sockstate->ov_read) {
                        matched = 1;
                        sockstate->masks &= ~READ_QUEUED;
                        if (sockstate->masks & AE_READABLE) {
                            eventLoop->fired[numevents].fd = rfd;
                            eventLoop->fired[numevents].mask = AE_READABLE;
                            numevents++;
                        }
                    } else if (sockstate->wreqs > 0 && entry->lpOverlapped != NULL) {
                        /* should be write complete. Get results */
                        asendreq *areq = (asendreq *)entry->lpOverlapped;
                        matched = removeMatchFromList(&sockstate->wreqlist, areq);
                        if (matched) {
                            /* call write complete callback so buffers can be freed */
                            if (areq->proc != NULL) {
                                DWORD written = 0;
                                DWORD flags;
                                WSAGetOverlappedResult(rfd, &areq->ov, &written, FALSE, &flags);
                                areq->proc(areq->eventLoop, rfd, &areq->req, (int)written);
                            }
                            sockstate->wreqs--;
                            zfree(areq);
                            /* if no active write requests, set ready to write */
                            if (sockstate->wreqs == 0 && sockstate->masks & AE_WRITABLE) {
                                eventLoop->fired[numevents].fd = rfd;
                                eventLoop->fired[numevents].mask = AE_WRITABLE;
                                numevents++;
                            }
                        }
                    }
                    if (matched == 0) {
                        /* redisLog */printf("Sec:%lld Unknown complete (closed) on %d\n", gettimeofdaysecs(NULL), rfd);
                        sockstate = NULL;
                    }
                }
            } else {
                // no match for active connection.
                // Try the closing list.
                list *socklist = &(state->closing);
                listNode *node;
                node = listFirst(socklist);
                while (node != NULL) {
                    sockstate = (aeSockState *)listNodeValue(node);
                    if (sockstate->fd == rfd) {
                        if (sockstate->masks & CONNECT_PENDING) {
                            /* check if connect complete */
                            if (entry->lpOverlapped == &sockstate->ov_read) {
                                sockstate->masks &= ~CONNECT_PENDING;
                            }
                        } else if (entry->lpOverlapped == &sockstate->ov_read) {
                            // read complete
                            sockstate->masks &= ~READ_QUEUED;
                        } else {
                            // check pending writes
                            asendreq *areq = (asendreq *)entry->lpOverlapped;
                            if (removeMatchFromList(&sockstate->wreqlist, areq)) {
                                sockstate->wreqs--;
                                zfree(areq);
                            }
                        }
                        if (sockstate->wreqs == 0 &&
                            (sockstate->masks & (CONNECT_PENDING | READ_QUEUED | SOCKET_ATTACHED)) == 0) {
                            if ((sockstate->masks & CLOSE_PENDING) != 0) {
                                close(rfd);
                                sockstate->masks &= ~(CLOSE_PENDING);
                            }
                            // safe to delete sockstate
                            aeDelSockState(state, sockstate);
                        }
                        break;
                    }
                    node = listNextNode(node);
                }
            }
        }
    }
    return numevents;
}
예제 #6
0
파일: ae_select.c 프로젝트: 3xian/beansdb
static int aeApiUpdateEvent(EventLoop *eventLoop, int fd, int mask) {
    return aeApiAddEvent(eventLoop, fd, mask);
}
예제 #7
0
/* Return array of sockets that are ready for read or write
 * depending on the mask for each socket */
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp) {
    aeApiState *state = (aeApiState *) eventLoop->apidata;
    iocpSockState *sockstate;
    ULONG j;
    int numevents = 0;
    ULONG numComplete = 0;
    BOOL rc;
    int mswait = (tvp == NULL) ? 100 : (tvp->tv_sec * 1000) + (tvp->tv_usec / 1000);

    if (pGetQueuedCompletionStatusEx != NULL) {
        // First get an array of completion notifications
        rc = pGetQueuedCompletionStatusEx(state->iocp,
                                          state->entries,
                                          MAX_COMPLETE_PER_POLL,
                                          &numComplete,
                                          mswait,
                                          FALSE);
    } else {
        // Need to get one at a time. Use first array element
        rc = GetQueuedCompletionStatus(state->iocp,
                                       &state->entries[0].dwNumberOfBytesTransferred,
                                       &state->entries[0].lpCompletionKey,
                                       &state->entries[0].lpOverlapped,
                                       mswait);
        if (!rc && state->entries[0].lpOverlapped == NULL) {
            // Timeout. Return.
            return 0;
        } else {
            // Check if more completions are ready
            BOOL lrc = TRUE;
            rc = TRUE;
            numComplete = 1;

            while (numComplete < MAX_COMPLETE_PER_POLL) {
                lrc = GetQueuedCompletionStatus(state->iocp,
                                                &state->entries[numComplete].dwNumberOfBytesTransferred,
                                                &state->entries[numComplete].lpCompletionKey,
                                                &state->entries[numComplete].lpOverlapped,
                                                0);
                if (lrc) {
                    numComplete++;
                } else {
                    if (state->entries[numComplete].lpOverlapped == NULL) break;
                }
            }
        }
    }

    if (rc && numComplete > 0) {
        LPOVERLAPPED_ENTRY entry = state->entries;
        for (j = 0; j < numComplete && numevents < state->setsize; j++, entry++) {
            // The competion key is the rfd identifying the socket 
            int rfd = (int) entry->lpCompletionKey;
            sockstate = WSIOCP_GetExistingSocketState(rfd);
            if (sockstate == NULL) {
                continue;
            }

            if ((sockstate->masks & CLOSE_PENDING) == FALSE) {
                if ((sockstate->masks & LISTEN_SOCK) && entry->lpOverlapped != NULL) {
                    // Need to set event for listening
                    aacceptreq *areq = (aacceptreq *) entry->lpOverlapped;
                    areq->next = sockstate->reqs;
                    sockstate->reqs = areq;
                    sockstate->masks &= ~ACCEPT_PENDING;
                    if (sockstate->masks & AE_READABLE) {
                        eventLoop->fired[numevents].fd = rfd;
                        eventLoop->fired[numevents].mask = AE_READABLE;
                        numevents++;
                    }
                } else if (sockstate->masks & CONNECT_PENDING) {
                    // Check if connect complete
                    if (entry->lpOverlapped == &sockstate->ov_read) {
                        sockstate->masks &= ~CONNECT_PENDING;
                        // Enable read and write events for this connection
                        aeApiAddEvent(eventLoop, rfd, sockstate->masks);
                    }
                } else {
                    BOOL matched = FALSE;
                    // Check if event is read complete (may be 0 length read)
                    if (entry->lpOverlapped == &sockstate->ov_read) {
                        matched = TRUE;
                        sockstate->masks &= ~READ_QUEUED;
                        if (sockstate->masks & AE_READABLE) {
                            eventLoop->fired[numevents].fd = rfd;
                            eventLoop->fired[numevents].mask = AE_READABLE;
                            numevents++;
                        }
                    } else if (sockstate->wreqs > 0 && entry->lpOverlapped != NULL) {
                        // Should be write complete. Get results
                        asendreq *areq = (asendreq *) entry->lpOverlapped;
                        matched = removeMatchFromList(&sockstate->wreqlist, areq);
                        if (matched == TRUE) {
                            // Call write complete callback so buffers can be freed
                            if (areq->proc != NULL) {
                                DWORD written = 0;
                                DWORD flags;
                                FDAPI_WSAGetOverlappedResult(rfd, &areq->ov, &written, FALSE, &flags);
                                areq->proc(areq->eventLoop, rfd, &areq->req, (int) written);
                            }
                            sockstate->wreqs--;
                            FreeMemoryNoCOW(areq);
                            // If no active write requests, set ready to write
                            if (sockstate->wreqs == 0 && sockstate->masks & AE_WRITABLE) {
                                eventLoop->fired[numevents].fd = rfd;
                                eventLoop->fired[numevents].mask = AE_WRITABLE;
                                numevents++;
                            }
                        }
                    }
                    if (matched == 0 && sockstate->unknownComplete == 0) {
                        sockstate->unknownComplete = 1;
                        close(rfd);
                    }
                }
            } else {
                if (sockstate->masks & CONNECT_PENDING) {
                    // Check if connect complete
                    if (entry->lpOverlapped == &sockstate->ov_read) {
                        sockstate->masks &= ~CONNECT_PENDING;
                    }
                } else if (entry->lpOverlapped == &sockstate->ov_read) {
                    // Read complete
                    sockstate->masks &= ~READ_QUEUED;
                } else {
                    // Check pending writes
                    asendreq *areq = (asendreq *) entry->lpOverlapped;
                    if (removeMatchFromList(&sockstate->wreqlist, areq)) {
                        sockstate->wreqs--;
                        FreeMemoryNoCOW(areq);
                    }
                }
                if (sockstate->wreqs == 0 &&
                    (sockstate->masks & (CONNECT_PENDING | READ_QUEUED | SOCKET_ATTACHED)) == 0) {
                    sockstate->masks &= ~(CLOSE_PENDING);
                    if (WSIOCP_CloseSocketState(sockstate)) {
                        FDAPI_ClearSocketInfo(rfd);
                    }
                }
            }
        }
    }
    return numevents;
}