Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Solaris Abstraction Layer (SAL)
0003  *
0004  * @file sys_solaris.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 
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 <dirent.h>
0050 #include <stdarg.h>
0051 
0052 #include <ndrstandard.h>
0053 #include <ndebug.h>
0054 #include <nstdutil.h>
0055 #include <limits.h>
0056 
0057 #include <sys_mqueue.h>
0058 #include <sys_unix.h>
0059 
0060 #include <utlist.h>
0061 
0062 
0063 /*---------------------------Externs------------------------------------*/
0064 /*---------------------------Macros-------------------------------------*/
0065 #define SOL_RND_SLEEP   10000 /* 0.01 sec */
0066 /*---------------------------Enums--------------------------------------*/
0067 /*---------------------------Typedefs-----------------------------------*/
0068 /*---------------------------Globals------------------------------------*/
0069 /*---------------------------Statics------------------------------------*/
0070 /*---------------------------Prototypes---------------------------------*/
0071 
0072 #ifdef EX_USE_POLL
0073 /**
0074  * Return the list of queues (build the list according to /tmp/.MQD files.
0075  * e.g ".MQPn00b,srv,admin,atmi.sv1,123,2229" translates as
0076  * "/n00b,srv,admin,atmi.sv1,123,2229")
0077  * the qpath must point to /tmp
0078  */
0079 expublic string_list_t* ndrx_sys_mqueue_list_make_pl(char *qpath, int *return_status)
0080 {
0081     string_list_t* ret = NULL;
0082     struct dirent **namelist;
0083     int n;
0084     string_list_t* tmp;
0085     int len;
0086     
0087     *return_status = EXSUCCEED;
0088     
0089     n = scandir(qpath, &namelist, 0, alphasort);
0090     if (n < 0)
0091     {
0092         NDRX_LOG(log_error, "Failed to open queue directory: %s", 
0093                 strerror(errno));
0094         goto exit_fail;
0095     }
0096     else 
0097     {
0098         while (n--)
0099         {
0100             if (0==strcmp(namelist[n]->d_name, ".") || 
0101                         0==strcmp(namelist[n]->d_name, "..") ||
0102                         0!=strncmp(namelist[n]->d_name, ".MQP", 4))
0103             {
0104                 NDRX_FREE(namelist[n]);
0105                 continue;
0106             }
0107             
0108             len = strlen(namelist[n]->d_name) -3 /*.MQP*/ + 1 /* EOS */;
0109             
0110             if (NULL==(tmp = NDRX_CALLOC(1, sizeof(string_list_t))))
0111             {
0112                 NDRX_LOG(log_always, "alloc of string_list_t (%d) failed: %s", 
0113                         sizeof(string_list_t), strerror(errno));
0114                 
0115                 
0116                 goto exit_fail;
0117             }
0118             
0119             if (NULL==(tmp->qname = NDRX_MALLOC(len)))
0120             {
0121                 NDRX_LOG(log_always, "alloc of %d bytes failed: %s", 
0122                         len, strerror(errno));
0123                 NDRX_FREE(tmp);
0124                 goto exit_fail;
0125             }
0126             
0127             strcpy(tmp->qname, "/");
0128             strcat(tmp->qname, namelist[n]->d_name+4); /* strip off .MQP */
0129             
0130             /* Add to LL */
0131             LL_APPEND(ret, tmp);
0132             
0133             NDRX_FREE(namelist[n]);
0134         }
0135         NDRX_FREE(namelist);
0136     }
0137     
0138     return ret;
0139     
0140 exit_fail:
0141 
0142     *return_status = EXFAIL;
0143 
0144     if (NULL!=ret)
0145     {
0146         ndrx_string_list_free(ret);
0147         ret = NULL;
0148     }
0149 
0150     return ret;   
0151 }
0152 
0153 /**
0154  * Wrapper for solaris bugfix Bug #128
0155  * On undocumented error EBUSY, retry the call. Seems to help.
0156  */
0157 expublic inline int sol_mq_close(mqd_t mqdes)
0158 {
0159     int ret;
0160     int err;
0161 
0162     while (EXSUCCEED!=(ret = mq_close(mqdes)) && (err=errno)==EBUSY)
0163     {
0164 /*  NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__);*/
0165         usleep(SOL_RND_SLEEP);
0166     }
0167 
0168     errno = err;
0169     return ret; 
0170 }
0171 
0172 /**
0173  * Wrapper for solaris bugfix Bug #128
0174  * On undocumented error EBUSY, retry the call. Seems to help.
0175  */
0176 expublic inline int  sol_mq_getattr(mqd_t mqdes, struct mq_attr * attr)
0177 {
0178     int ret;
0179     int err;
0180 
0181     while (EXSUCCEED!=(ret = mq_getattr(mqdes, attr)) && ((err=errno)==EBUSY))
0182     {
0183     /*  NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__); */
0184             usleep(SOL_RND_SLEEP);
0185     }
0186     errno = err;
0187     return ret;
0188 }
0189 
0190 /**
0191  * Wrapper for solaris bugfix Bug #128
0192  * On undocumented error EBUSY, retry the call. Seems to help.
0193  */
0194 expublic inline int sol_mq_notify(mqd_t mqdes, struct sigevent * sevp)
0195 {
0196     int ret;
0197     int err;
0198 
0199     NDRX_LOG(log_warn, "%s: mqdes=%d", __func__, mqdes);
0200     while (EXSUCCEED!=(ret =mq_notify(mqdes, sevp)) && ((err=errno)==EBUSY))
0201     {
0202             NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__);
0203             usleep(SOL_RND_SLEEP);
0204     }
0205     errno =err;
0206     return ret;
0207 }
0208 
0209 /**
0210  * Wrapper for solaris bugfix Bug #128
0211  * On undocumented error EBUSY, retry the call. Seems to help.
0212  */
0213 expublic inline mqd_t   sol_mq_open(char *name, int oflag, mode_t mode, struct mq_attr *attr)
0214 {
0215     mqd_t  ret;
0216     int err;
0217 
0218     while (EXFAIL==(int)(ret = mq_open(name, oflag, mode, attr)) && 
0219             ((err=errno)==EBUSY))
0220     {
0221             usleep(SOL_RND_SLEEP);
0222     }
0223 
0224     errno = err;
0225     return ret; 
0226 }
0227 
0228 /**
0229  * Wrapper for solaris bugfix Bug #128
0230  * On undocumented error EBUSY, retry the call. Seems to help.
0231  */
0232 expublic inline ssize_t sol_mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, 
0233                 unsigned int *msg_prio)
0234 {
0235     ssize_t ret;
0236     int err;
0237 
0238     while (EXFAIL==(ret =mq_receive(mqdes, msg_ptr, msg_len, msg_prio)) && 
0239             ((err=errno)==EBUSY))
0240     {
0241 /*  NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__); */
0242         usleep(SOL_RND_SLEEP);
0243     }
0244     errno = err;
0245     return ret;
0246 }
0247 
0248 /**
0249  * Wrapper for solaris bugfix Bug #128
0250  * On undocumented error EBUSY, retry the call. Seems to help.
0251  */
0252 expublic inline int sol_mq_send(mqd_t mqdes, char *msg_ptr, size_t msg_len,
0253                     unsigned int msg_prio)
0254 {
0255     int ret;
0256     int err;
0257     
0258     while (EXSUCCEED!=(ret =mq_send(mqdes, msg_ptr, msg_len, msg_prio)) &&
0259             ((err=errno)==EBUSY))
0260     {
0261 /*  NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__); */
0262         usleep(SOL_RND_SLEEP);
0263     }
0264     errno = err;
0265     return ret;
0266 }
0267 
0268 /**
0269  * Wrapper for solaris bugfix Bug #128
0270  * On undocumented error EBUSY, retry the call. Seems to help.
0271  */
0272 expublic inline int sol_mq_setattr(mqd_t mqdes,
0273                        struct mq_attr * newattr,
0274                        struct mq_attr * oldattr)
0275 {
0276     int ret;
0277     int err;
0278 
0279     while (EXSUCCEED!=(ret =mq_setattr(mqdes, newattr, oldattr)) &&
0280             ((err=errno)==EBUSY))
0281     {
0282 /*  NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__); */
0283     usleep(SOL_RND_SLEEP);
0284     }
0285     errno = err;
0286     return ret;
0287 }
0288 
0289 /**
0290  * Wrapper for solaris bugfix Bug #128
0291  * On undocumented error EBUSY, retry the call. Seems to help.
0292  */
0293 expublic inline int sol_mq_unlink(char *name)
0294 {
0295     int ret;
0296     int err;
0297 
0298     while (EXSUCCEED!=(ret =mq_unlink(name)) &&
0299             ((err=errno)==EBUSY))
0300     {
0301     /* NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__); */
0302     usleep(SOL_RND_SLEEP);
0303     }
0304     errno = err;
0305     return ret;
0306 }
0307 
0308 /**
0309  * Wrapper for solaris bugfix Bug #128
0310  * On undocumented error EBUSY, retry the call. Seems to help.
0311  */
0312 expublic inline int sol_mq_timedsend(mqd_t mqdes, char *msg_ptr, size_t len, 
0313                   unsigned int msg_prio, struct timespec *abs_timeout)
0314 {
0315     int ret;
0316     int err;
0317 
0318     while (EXSUCCEED!=(ret =mq_timedsend(mqdes, msg_ptr, len, msg_prio, abs_timeout)) &&
0319             ((err=errno)==EBUSY))
0320     {
0321 /*  NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__); */
0322             usleep(SOL_RND_SLEEP);
0323     }
0324     errno = err;
0325     return ret;
0326 }
0327 
0328 /**
0329  * Wrapper for solaris bugfix Bug #128
0330  * On undocumented error EBUSY, retry the call. Seems to help.
0331  */
0332 expublic inline  ssize_t sol_mq_timedreceive(mqd_t mqdes, char *msg_ptr,
0333      size_t  msg_len,  unsigned  *msg_prio, struct
0334      timespec *abs_timeout)
0335 {
0336     ssize_t ret;
0337     int err;
0338 
0339     while (EXFAIL==(ret =mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, abs_timeout)) &&
0340             ((err=errno)==EBUSY))
0341     {
0342 /*      NDRX_LOG(log_warn, "%s: got EBUSY - restarting call...", __func__);*/
0343         usleep(SOL_RND_SLEEP);
0344     }
0345     errno = err;
0346     return ret;
0347 }
0348 
0349 #endif /* EX_USE_POLL */
0350 
0351 /**
0352  * Test the pid to contain regexp 
0353  * @param pid process id to test
0354  * @param p_re compiled regexp to test against
0355  * @return -1 failed, 0 - not matched, 1 - matched
0356  */
0357 expublic int ndrx_sys_env_test(pid_t pid, regex_t *p_re)
0358 {
0359     return ndrx_sys_cmdout_test("pargs -ae %d 2>/dev/null", pid, p_re);
0360 }
0361 
0362 /* vim: set ts=4 sw=4 et smartindent: */