Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Kqueue Abstraction Layer (KAL) for BSD
0003  *
0004  * @file sys_kqueue.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 
0035 /*---------------------------Includes-----------------------------------*/
0036 #include <stdio.h>
0037 #include <stdlib.h>
0038 #include <time.h>
0039 
0040 #include <unistd.h>
0041 #include <stdarg.h>
0042 #include <ctype.h>
0043 #include <memory.h>
0044 #include <errno.h>
0045 #include <signal.h>
0046 #include <limits.h>
0047 #include <pthread.h>
0048 #include <string.h>
0049 #include <sys/event.h>
0050 
0051 #include <ndrstandard.h>
0052 #include <ndebug.h>
0053 #include <nstdutil.h>
0054 #include <limits.h>
0055 
0056 #include <sys_unix.h>
0057 
0058 
0059 /*---------------------------Externs------------------------------------*/
0060 /*---------------------------Macros-------------------------------------*/
0061 /*---------------------------Enums--------------------------------------*/
0062 /*---------------------------Typedefs-----------------------------------*/
0063 /*---------------------------Globals------------------------------------*/
0064 /*---------------------------Statics------------------------------------*/
0065 /*---------------------------Prototypes---------------------------------*/
0066 
0067 /**
0068  * Nothing to init for epoll()
0069  */
0070 expublic int ndrx_epoll_sys_init(void)
0071 {
0072     return EXSUCCEED;
0073 }
0074 
0075 /**
0076  * Nothing to un-init for epoll()
0077  */
0078 expublic inline void ndrx_epoll_sys_uninit(void)
0079 {
0080     return;
0081 }
0082 
0083 /**
0084  * Return the compiled poll mode
0085  * @return 
0086  */
0087 expublic inline char * ndrx_epoll_mode(void)
0088 {
0089     static char *mode = "kqueue";
0090     
0091     return mode;
0092 }
0093 /**
0094  * Wrapper for epoll_ctl, for standard file descriptors
0095  * @param epfd
0096  * @param op
0097  * @param fd
0098  * @param event
0099  * @return 
0100  */
0101 expublic inline int ndrx_epoll_ctl(int epfd, int op, int fd, struct ndrx_epoll_event *event)
0102 {   
0103     int ret = EXSUCCEED;
0104     char *fn = "ndrx_epoll_ctl";
0105     struct kevent ev;
0106     
0107     ev.udata = NULL;
0108 
0109     if (EX_EPOLL_CTL_ADD == op)
0110     {
0111         NDRX_LOG(log_info, "%s: Add operation on ndrx_epoll set %d, fd %d", fn, epfd, fd);
0112         
0113         EV_SET(&ev, fd, event->events, EV_ADD, 0, 0, NULL);
0114         
0115         return kevent(epfd, &ev, 1, NULL, 0, NULL);
0116     }
0117     else if (EX_EPOLL_CTL_DEL == op)
0118     {
0119         NDRX_LOG(log_info, "%s: Delete operation on ndrx_epoll set %d, fd %d", fn, epfd, fd);
0120            
0121         EV_SET(&ev,fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
0122         
0123         return kevent(epfd, &ev, 1, NULL, 0, NULL);
0124     }
0125     else
0126     {
0127         NDRX_LOG(log_error, "Invalid operation %d", op);
0128     errno = EINVAL;
0129         EXFAIL_OUT(ret);
0130     }
0131     
0132 out:
0133 
0134     NDRX_LOG(log_info, "%s return %d", fn, ret);
0135 
0136     return ret;
0137 }
0138 
0139 /**
0140  * epoll_ctl for Posix queue descriptors
0141  * @param epfd
0142  * @param op
0143  * @param fd
0144  * @param event
0145  * @return 
0146  */
0147 expublic inline int ndrx_epoll_ctl_mq(int epfd, int op, mqd_t fd, struct ndrx_epoll_event *event)
0148 {
0149     int ret = EXSUCCEED;
0150     char *fn = "ndrx_epoll_ctl";
0151     struct kevent ev;
0152     void *tmp = fd;
0153     int real_fd = *((int *)tmp);
0154 
0155     /* for bsd the file descriptor must be dereferenced from pointer */
0156 
0157     if (EX_EPOLL_CTL_ADD == op)
0158     {
0159         NDRX_LOG(log_info, "%s: Add operation on ndrx_epoll set %d, fd %d", fn, epfd, fd);
0160 
0161         EV_SET(&ev, real_fd, EVFILT_READ, event->events, 0, 0, NULL);
0162         ev.udata = fd;
0163 
0164         return kevent(epfd, &ev, 1, NULL, 0, NULL);
0165     }
0166     else if (EX_EPOLL_CTL_DEL == op)
0167     {
0168         NDRX_LOG(log_info, "%s: Delete operation on ndrx_epoll set %d, fd %d", fn, epfd, fd);
0169 
0170         EV_SET(&ev, real_fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
0171 
0172         return kevent(epfd, &ev, 1, NULL, 0, NULL);
0173     }
0174     else
0175     {
0176         NDRX_LOG(log_error, "Invalid operation %d", op);
0177         errno = EINVAL;
0178         EXFAIL_OUT(ret);
0179     }
0180 
0181 out:
0182 
0183     NDRX_LOG(log_info, "%s return %d", fn, ret);
0184 
0185     return ret;
0186 
0187 }
0188 
0189 /**
0190  * Wrapper for epoll_create
0191  * @param size
0192  * @return 
0193  */
0194 expublic inline int ndrx_epoll_create(int size)
0195 {
0196     return kqueue();
0197 }
0198 
0199 /**
0200  * Close Epoll set.
0201  */
0202 expublic inline int ndrx_epoll_close(int epfd)
0203 {
0204     return close(epfd);
0205 }
0206 
0207 /**
0208  * Wrapper for epoll_wait
0209  * @param epfd
0210  * @param events
0211  * @param maxevents
0212  * @param timeout
0213  * @param buf not used
0214  * @param buf_len not used
0215  * @return 
0216  */
0217 expublic int ndrx_epoll_wait(int epfd, struct ndrx_epoll_event *events,
0218         int maxevents, int timeout, char **buf, int *buf_len)
0219 {
0220     int ret = EXSUCCEED;
0221     int err_saved;
0222     int numevents = 0;
0223     char *fn = "ndrx_epoll_wait";
0224     int i;
0225     int retpoll;
0226     struct kevent tevent;    /* Event triggered */
0227     struct timespec tout;
0228     
0229     *buf_len = EXFAIL;
0230 
0231     if (timeout>0)
0232     {
0233         NDRX_LOG(log_debug, "about to kevent wait %d, timeout %d", epfd, timeout);
0234         tout.tv_nsec = 0;
0235         tout.tv_sec = timeout/1000;
0236         retpoll = kevent(epfd, NULL, 0, &tevent, 1, &tout);
0237     }
0238     else
0239     {
0240         NDRX_LOG(log_debug, "about to kevent wait %d, no timeout", epfd);
0241         retpoll = kevent(epfd, NULL, 0, &tevent, 1, NULL);
0242     }
0243     
0244     err_saved = errno;
0245     
0246     
0247     if (retpoll > 0)
0248     {
0249         /* 1 event currently supported... */
0250         NDRX_LOG(log_debug, "fd=%d, i=%d revents=%u", 
0251                 tevent.ident, tevent.flags);
0252 
0253         numevents++;
0254 
0255         if (tevent.udata!=NULL)
0256         {
0257             /* the mqueue hanlder is encoded here (ptr to fd..)*/
0258             events[numevents-1].data.mqd = (mqd_t)tevent.udata;
0259             events[numevents-1].is_mqd = EXTRUE;
0260         }
0261         else
0262         {
0263            events[numevents-1].data.fd = tevent.ident;
0264            events[numevents-1].is_mqd = EXFALSE;
0265         }
0266         /* will provide back both flags & flag flags... */
0267         events[numevents-1].events = tevent.flags;
0268     }
0269     else if (retpoll==0)
0270     {
0271         goto out;
0272     }
0273     else
0274     {
0275         EXFAIL_OUT(ret);
0276     }
0277     
0278 out:
0279 
0280     NDRX_LOG(log_info, "%s ret=%d numevents=%d", fn, ret, numevents);
0281 
0282     if (EXSUCCEED==ret)
0283     {
0284         return numevents;
0285     }
0286     else
0287     {
0288         errno = err_saved;
0289         return EXFAIL;
0290     }
0291 }
0292 
0293 
0294 /**
0295  * Return errno for ndrx_poll() operation
0296  * @return 
0297  */
0298 expublic inline int ndrx_epoll_errno(void)
0299 {
0300     return errno;
0301 }
0302 
0303 /**
0304  * Wrapper for strerror
0305  * @param err
0306  * @return 
0307  */
0308 expublic inline char * ndrx_poll_strerror(int err)
0309 {
0310     return strerror(err);
0311 }
0312 
0313 /**
0314  * not used by Kqueue epoll()
0315  * @param idx
0316  * @return 
0317  */
0318 expublic int ndrx_epoll_shallopenq(int idx)
0319 {
0320     return EXTRUE;
0321 }
0322 /**
0323  * Not used by Kqueue epoll()
0324  * @param qstr
0325  */
0326 expublic void ndrx_epoll_mainq_set(char *qstr)
0327 {
0328     return;
0329 }
0330 
0331 /**
0332  * Not used by Kqueue epoll
0333  * @param svcnm
0334  * @param idx
0335  * @param mq_exits
0336  * @return 
0337  */
0338 expublic mqd_t ndrx_epoll_service_add(char *svcnm, int idx, mqd_t mq_exits)
0339 {
0340     return mq_exits;
0341 }
0342 
0343 /**
0344  * Not used by linux epoll
0345  * @return 
0346  */
0347 expublic int ndrx_epoll_shmdetach(void)
0348 {
0349     return EXSUCCEED;
0350 }
0351 
0352 /**
0353  * Not used by Kqueue epoll
0354  * @param force
0355  * @return 
0356  */
0357 expublic int ndrx_epoll_down(int force)
0358 {
0359     return EXSUCCEED;
0360 }
0361 
0362 /* vim: set ts=4 sw=4 et smartindent: */