Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief EnduroX server poller extension.
0003  *   TODO: Use hash table for searching for FD!
0004  *
0005  * @file pollextension.c
0006  */
0007 /* -----------------------------------------------------------------------------
0008  * Enduro/X Middleware Platform for Distributed Transaction Processing
0009  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0010  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0011  * This software is released under one of the following licenses:
0012  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0013  * See LICENSE file for full text.
0014  * -----------------------------------------------------------------------------
0015  * AGPL license:
0016  *
0017  * This program is free software; you can redistribute it and/or modify it under
0018  * the terms of the GNU Affero General Public License, version 3 as published
0019  * by the Free Software Foundation;
0020  *
0021  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0022  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0023  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0024  * for more details.
0025  *
0026  * You should have received a copy of the GNU Affero General Public License along 
0027  * with this program; if not, write to the Free Software Foundation, Inc.,
0028  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0029  *
0030  * -----------------------------------------------------------------------------
0031  * A commercial use license is available from Mavimax, Ltd
0032  * contact@mavimax.com
0033  * -----------------------------------------------------------------------------
0034  */
0035 
0036 /*---------------------------Includes-----------------------------------*/
0037 #include <ndrx_config.h>
0038 #include <stdio.h>
0039 #include <stdlib.h>
0040 #include <errno.h>
0041 
0042 #include <ndrstandard.h>
0043 #include <ndebug.h>
0044 #include <utlist.h>
0045 #include <string.h>
0046 #include "srv_int.h"
0047 #include "tperror.h"
0048 #include <atmi_int.h>
0049 #include <atmi_shm.h>
0050 /*---------------------------Externs------------------------------------*/
0051 /*---------------------------Macros-------------------------------------*/
0052 /*---------------------------Enums--------------------------------------*/
0053 /*---------------------------Typedefs-----------------------------------*/
0054 /*---------------------------Globals------------------------------------*/
0055 pollextension_rec_t * ndrx_G_pollext=NULL;
0056 exprivate int M_pollsync = EXTRUE; /**< Shall we change the pool struct? */
0057 /*---------------------------Statics------------------------------------*/
0058 /*---------------------------Prototypes---------------------------------*/
0059 
0060 
0061 /**
0062  * Compares two buffers in linked list (for search purposes)
0063  * @param a
0064  * @param b
0065  * @return 0 - equal/ -1 - not equal
0066  */
0067 exprivate int ext_find_poller_cmp(pollextension_rec_t *a, pollextension_rec_t *b)
0068 {
0069     return (a->fd==b->fd?EXSUCCEED:EXFAIL);
0070 }
0071 
0072 
0073 /**
0074  * Set the poll sync flag.
0075  * If set to false, no main poll is changed
0076  * (if using custom thread)
0077  * @param flag EXTRUE/EXFALSE
0078  */
0079 expublic void ndrx_ext_pollsync(int flag)
0080 {
0081     M_pollsync=flag;
0082     NDRX_LOG(log_info, "Extension poll sync flag set to: %d", M_pollsync);
0083 }
0084 
0085 /**
0086  * Find the buffer in list of known buffers
0087  * @param ptr
0088  * @return NULL - buffer not found/ptr - buffer found
0089  */
0090 expublic pollextension_rec_t * ext_find_poller(int fd)
0091 {
0092     pollextension_rec_t *ret=NULL, eltmp;
0093 
0094     eltmp.fd = fd;
0095     DL_SEARCH(ndrx_G_pollext, ret, &eltmp, ext_find_poller_cmp);
0096     
0097     return ret;
0098 }
0099 
0100 /**
0101  * Extension for polling.
0102  * @param fd
0103  * @param events
0104  * @param p_pollevent
0105  * @return 
0106  */
0107 expublic int _tpext_addpollerfd(int fd, uint32_t events, 
0108         void *ptr1, int (*p_pollevent)(int fd, uint32_t events, void *ptr1))
0109 {
0110     int ret=EXSUCCEED;
0111     pollextension_rec_t * pollext = NULL;
0112     pollextension_rec_t * existing = NULL;
0113     struct ndrx_epoll_event ev;
0114     
0115     if (NULL==G_server_conf.service_array &&  M_pollsync)
0116     {
0117         ndrx_TPset_error_fmt(TPEPROTO, "Cannot add custom poller at init stage!");
0118         ret=EXFAIL;
0119         goto out;
0120     }
0121     
0122     /* Search for existing stuff, will search for FD */
0123     existing = ext_find_poller(fd);
0124     if (NULL!=existing)
0125     {
0126         ndrx_TPset_error_fmt(TPEMATCH, "Poller for fd %d already exists", fd);
0127         NDRX_LOG(log_error, "Poller for fd %d already exists!", fd);
0128         ret=EXFAIL;
0129         goto out;
0130     }
0131     
0132     pollext = NDRX_MALLOC(sizeof(pollextension_rec_t));
0133     if (NULL==pollext)
0134     {
0135         ndrx_TPset_error_fmt(TPEOS, "failed to malloc pollextension_rec_t (%d bytes): %s", 
0136                 sizeof(pollextension_rec_t), strerror(errno));
0137         ret=EXFAIL;
0138         goto out;
0139     }    
0140     
0141     if (M_pollsync)
0142     {
0143         /* We are good to go! Add epoll stuff here */
0144         ev.events = events; /* hmmm what to do? */
0145         ev.data.fd = fd;
0146 
0147         if (EXFAIL==ndrx_epoll_ctl(G_server_conf.epollfd, EX_EPOLL_CTL_ADD,
0148                                 fd, &ev))
0149         {
0150             ndrx_TPset_error_fmt(TPEOS, "epoll_ctl failed: %s", 
0151                     ndrx_poll_strerror(ndrx_epoll_errno()));
0152             ret=EXFAIL;
0153             goto out;
0154         }
0155     }
0156     
0157     /* Add stuff to doubly linked list! */
0158     pollext->p_pollevent = p_pollevent;
0159     pollext->fd = fd;
0160     pollext->ptr1 = ptr1;
0161 /*
0162     Does not build on AIX!
0163     pollext->events = events;
0164 */
0165     
0166     DL_APPEND(ndrx_G_pollext, pollext);
0167     NDRX_LOG(log_debug, "Function 0x%lx fd=%d successfully added "
0168             "for polling", p_pollevent, fd);
0169     
0170 out:
0171 
0172     /* Free resources if dead on arrival */
0173     if (EXSUCCEED!=ret && NULL!=pollext)
0174     {
0175         NDRX_FREE(pollext);
0176     }
0177 
0178     return ret;
0179 }
0180 
0181 /**
0182  * Remove polling FD
0183  * @param fd
0184  * @param events
0185  * @param p_pollevent
0186  * @return 
0187  */
0188 expublic int _tpext_delpollerfd(int fd)
0189 {
0190     int ret=EXSUCCEED;
0191     pollextension_rec_t * existing = NULL;
0192     
0193     if (NULL==G_server_conf.service_array && M_pollsync)
0194     {
0195         ndrx_TPset_error_fmt(TPEPROTO, "Cannot remove custom poller at init stage!");
0196         ret=EXFAIL;
0197         goto out;
0198     }
0199     
0200     /* Search for existing stuff, will search for FD */
0201     existing = ext_find_poller(fd);
0202     if (NULL==existing)
0203     {
0204         ndrx_TPset_error_fmt(TPEMATCH, "No polling extension found for fd %d", fd);
0205         ret=EXFAIL;
0206         goto out;
0207     }
0208 
0209     if (M_pollsync)
0210     {
0211         /* OK, stuff found, remove from Epoll */
0212         if (EXFAIL==ndrx_epoll_ctl(G_server_conf.epollfd, EX_EPOLL_CTL_DEL,
0213                             fd, NULL))
0214         {
0215             ndrx_TPset_error_fmt(TPEOS, "epoll_ctl failed to remove fd %d from epollfd: %s", 
0216                     fd, ndrx_poll_strerror(ndrx_epoll_errno()));
0217             ret=EXFAIL;
0218             goto out;
0219         }
0220     }
0221     
0222     /* Remove from linked list */
0223     DL_DELETE(ndrx_G_pollext, existing);
0224     NDRX_FREE(existing);
0225     
0226 out:
0227 
0228     return ret;
0229 }
0230 
0231 
0232 /**
0233  * Add periodical callback
0234  * @param secs
0235  * @param p_pollevent
0236  * @return 
0237  */
0238 expublic int _tpext_addperiodcb(int secs, int (*p_periodcb)(void))
0239 {
0240     int ret=EXSUCCEED;
0241     
0242     G_server_conf.p_periodcb = p_periodcb;
0243     G_server_conf.periodcb_sec = secs;
0244     NDRX_LOG(log_debug, "Registering periodic callback func ptr "
0245             "%p, period: %d sec(s)", 
0246             G_server_conf.p_periodcb, G_server_conf.periodcb_sec);
0247     
0248 out:
0249     return ret;
0250 }
0251 
0252 /**
0253  * Disable periodical callback.
0254  * @return 
0255  */
0256 expublic int _tpext_delperiodcb(void)
0257 {
0258     int ret=EXSUCCEED;
0259     
0260     NDRX_LOG(log_debug, "Disabling periodical callback, was: %p",
0261             G_server_conf.p_periodcb);
0262     G_server_conf.p_periodcb = NULL;
0263     G_server_conf.periodcb_sec = 0;
0264 out:
0265     return ret;
0266 }
0267 
0268 
0269 
0270 /**
0271  * Add before poll callback
0272  * @param secs
0273  * @param p_pollevent
0274  * @return 
0275  */
0276 expublic int _tpext_addb4pollcb(int (*p_b4pollcb)(void))
0277 {
0278     int ret=EXSUCCEED;
0279     
0280     G_server_conf.p_b4pollcb = p_b4pollcb;
0281     NDRX_LOG(log_debug, "Registering before poll callback func ptr "
0282             "0x%lx", 
0283             G_server_conf.p_b4pollcb);
0284     
0285 out:
0286     return ret;
0287 }
0288 
0289 /**
0290  * Disable before poll callback.
0291  * @return 
0292  */
0293 expublic int _tpext_delb4pollcb(void)
0294 {
0295     int ret=EXSUCCEED;
0296     
0297     NDRX_LOG(log_debug, "Disabling before poll callback, was: 0x%lx",
0298             G_server_conf.p_b4pollcb);
0299     G_server_conf.p_b4pollcb = NULL;
0300 out:
0301     return ret;
0302 }
0303 
0304 
0305 /**
0306  * Custom shutdown handler (currently internal, not exposed to outer world)
0307  * @param p_shutdowncb shutdown callback
0308  * @return EXSUCCEED
0309  */
0310 expublic int ndrx_tpext_addbshutdowncb(int (*p_shutdowncb)(int *shutdown_req))
0311 {
0312     int ret=EXSUCCEED;
0313     
0314     G_server_conf.p_shutdowncb = p_shutdowncb;
0315     NDRX_LOG(log_debug, "Registering shutdown func ptr %p",  G_server_conf.p_shutdowncb);
0316     
0317 out:
0318     return ret;
0319 }
0320 
0321 /* vim: set ts=4 sw=4 et smartindent: */