Annotation of libaitio/src/exec.c, revision 1.1.2.13

1.1.2.1   misho       1: #include "global.h"
                      2: 
                      3: 
                      4: /*
                      5:  * io_progInit() - Init program pool
                      6:  *
                      7:  * @progName = program name for execution
                      8:  * @initNum = initial started programs
                      9:  * @maxNum = maximum started programs
                     10:  * return: NULL error or !=NULL allocated pool (must destroied with io_progDestroy())
                     11:  */
                     12: prog_t *
                     13: io_progInit(const char *progName, u_int initNum, u_int maxNum)
                     14: {
                     15:        prog_t *prg = NULL;
                     16: 
                     17:        if (initNum > maxNum)
                     18:                return NULL;
                     19: 
                     20:        prg = e_malloc(sizeof(prog_t));
                     21:        if (!prg) {
                     22:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     23:                return NULL;
                     24:        } else
                     25:                memset(prg, 0, sizeof(prog_t));
                     26: 
                     27:        prg->prog_inin = initNum;
                     28:        prg->prog_maxn = maxNum;
                     29:        strlcpy(prg->prog_name, progName, sizeof prg->prog_name);
                     30: 
1.1.2.9   misho      31:        prg->prog_used = e_malloc(E_ALIGN(prg->prog_maxn, sizeof *prg->prog_used) / 
                     32:                        sizeof *prg->prog_used);
                     33:        if (!prg->prog_used) {
                     34:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                     35:                e_free(prg);
                     36:                return NULL;
                     37:        }
                     38: 
1.1.2.1   misho      39:        prg->prog_fds = array_Init(prg->prog_maxn);
                     40:        if (!prg->prog_fds) {
                     41:                io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.1.2.9   misho      42:                e_free(prg->prog_used);
1.1.2.1   misho      43:                e_free(prg);
                     44:                return NULL;
                     45:        }
                     46: 
                     47:        pthread_mutex_init(&prg->prog_mtx, NULL);
1.1.2.12  misho      48:        signal(SIGPIPE, SIG_IGN);
1.1.2.2   misho      49: 
1.1.2.6   misho      50:        if (io_progOpen(prg, prg->prog_inin) < 0) {
1.1.2.2   misho      51:                io_progDestroy(&prg);
1.1.2.6   misho      52:                prg = NULL;
                     53:        }
1.1.2.1   misho      54:        return prg;
                     55: }
                     56: 
                     57: /*
                     58:  * io_progDestroy() - Destroy entire program pool
                     59:  *
                     60:  * @pprg = program pool
                     61:  * return: none
                     62:  */
                     63: void
                     64: io_progDestroy(prog_t ** __restrict pprg)
                     65: {
                     66:        if (!pprg || !*pprg)
                     67:                return;
                     68: 
                     69:        io_progClose(*pprg, 0);
                     70: 
1.1.2.9   misho      71:        e_free((*pprg)->prog_used);
1.1.2.1   misho      72:        array_Destroy(&(*pprg)->prog_fds);
                     73:        pthread_mutex_destroy(&(*pprg)->prog_mtx);
1.1.2.13! misho      74:        signal(SIGPIPE, SIG_DFL);
1.1.2.1   misho      75: 
                     76:        e_free(*pprg);
                     77:        *pprg = NULL;
                     78: }
                     79: 
                     80: /*
                     81:  * io_progClose() - Close all programs in pool
                     82:  *
                     83:  * @prg = program pool
                     84:  * @closeNum = close program(s) (0 all)
                     85:  * return: 0 error, >0 closed programs
                     86:  */
                     87: int
                     88: io_progClose(prog_t * __restrict prg, u_int closeNum)
                     89: {
                     90:        register int i;
                     91:        int ret = 0;
                     92: 
                     93:        if (!prg)
                     94:                return 0;
                     95:        if (closeNum > prg->prog_maxn) {
                     96:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                     97:                return 0;
                     98:        }
                     99: 
                    100:        pthread_mutex_lock(&prg->prog_mtx);
                    101:        for (i = array_Size(prg->prog_fds) - 1; 
                    102:                        (closeNum ? ret < closeNum : 42) && i > -1; i--)
                    103:                if (array_Get(prg->prog_fds, i)) {
1.1.2.11  misho     104: #ifdef POPEN_STREAM
1.1.2.6   misho     105:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     106: #else
                    107:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    108: #endif
1.1.2.1   misho     109:                        array_Del(prg->prog_fds, i, 0);
1.1.2.9   misho     110:                        clrbit(prg->prog_used, i);
1.1.2.1   misho     111:                        prg->prog_cnum--;
                    112:                        ret++;
                    113:                }
                    114:        pthread_mutex_unlock(&prg->prog_mtx);
                    115: 
                    116:        return ret;
                    117: }
                    118: 
                    119: /*
                    120:  * io_progOpen() - Execute number of program(s)
                    121:  *
                    122:  * @prg = program pool
                    123:  * @execNum = execute program(s) (0 max)
                    124:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
                    125:  */
                    126: int
                    127: io_progOpen(prog_t * __restrict prg, u_int execNum)
                    128: {
1.1.2.11  misho     129: #ifdef POPEN_STREAM
1.1.2.1   misho     130:        FILE *f;
1.1.2.11  misho     131: #else
                    132:        int f;
                    133: #endif
1.1.2.4   misho     134:        int stat, ret = 0;
1.1.2.1   misho     135:        register int i;
1.1.2.4   misho     136:        pid_t pid;
1.1.2.1   misho     137: 
                    138:        if (!prg)
                    139:                return 0;
1.1.2.8   misho     140:        if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1   misho     141:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    142:                return 0;
                    143:        }
                    144: 
                    145:        pthread_mutex_lock(&prg->prog_mtx);
                    146:        for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
                    147:                if (!array_Get(prg->prog_fds, i)) {
1.1.2.6   misho     148:                        f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.11  misho     149: #ifdef POPEN_STREAM
1.1.2.1   misho     150:                        if (!f) {
1.1.2.11  misho     151: #else
                    152:                        if (f == -1) {
                    153: #endif
1.1.2.1   misho     154:                                LOGERR;
1.1.2.5   misho     155:                                ret = -1;
1.1.2.1   misho     156:                                break;
1.1.2.6   misho     157:                        } else if (waitpid(pid, &stat, WNOHANG)) {
                    158:                                io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                    159:                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.5   misho     160:                                ret = -1;
1.1.2.4   misho     161:                                break;
1.1.2.1   misho     162:                        } else
                    163:                                array_Set(prg->prog_fds, i, f);
                    164:                        prg->prog_cnum++;
                    165:                        ret++;
                    166:                }
                    167:        pthread_mutex_unlock(&prg->prog_mtx);
                    168: 
                    169:        return ret;
                    170: }
                    171: 
                    172: /*
1.1.2.8   misho     173:  * io_progGrow() - Execute to number of programs in pool
                    174:  *
                    175:  * @prg = program pool
                    176:  * @toNum = execute to number of programs (0 max)
                    177:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
                    178:  */
                    179: int
                    180: io_progGrow(prog_t * __restrict prg, u_int toNum)
                    181: {
                    182:        if (!prg)
                    183:                return 0;
                    184:        if (toNum > prg->prog_maxn) {
                    185:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    186:                return 0;
                    187:        }
                    188:        if (!toNum)
                    189:                toNum = prg->prog_maxn;
                    190: 
                    191:        return io_progOpen(prg, toNum - prg->prog_cnum);
                    192: }
                    193: 
                    194: /*
1.1.2.1   misho     195:  * io_progVacuum() - Vacuum pool to running number of programs
                    196:  *
                    197:  * @prg = program pool
                    198:  * @toNum = vacuum to number of programs (0 to init number)
                    199:  * return: 0 error or >0 closed programs
                    200:  */
                    201: int
                    202: io_progVacuum(prog_t * __restrict prg, u_int toNum)
                    203: {
                    204:        register int i;
                    205:        int ret = 0;
                    206: 
                    207:        if (!prg)
                    208:                return 0;
                    209:        if (toNum > prg->prog_maxn) {
                    210:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    211:                return 0;
                    212:        }
                    213:        if (!toNum)
                    214:                toNum = prg->prog_inin;
                    215: 
                    216:        pthread_mutex_lock(&prg->prog_mtx);
                    217:        for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.10  misho     218:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
1.1.2.11  misho     219: #ifdef POPEN_STREAM
1.1.2.6   misho     220:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     221: #else
                    222:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    223: #endif
1.1.2.1   misho     224:                        array_Del(prg->prog_fds, i, 0);
                    225:                        prg->prog_cnum--;
                    226:                        ret++;
                    227:                }
                    228:        pthread_mutex_unlock(&prg->prog_mtx);
                    229: 
                    230:        return ret;
                    231: }
1.1.2.7   misho     232: 
                    233: /*
                    234:  * io_progCheck() - Check exit status of program pool
                    235:  *
                    236:  * @prg = program pool
                    237:  * return: -1 error or >-1 exited programs
                    238:  */
                    239: int
                    240: io_progCheck(prog_t * __restrict prg)
                    241: {
                    242:        int ret = 0;
                    243:        struct tagPIOPID *p;
                    244:        register int i;
                    245: 
                    246:        if (!prg)
                    247:                return -1;
                    248: 
1.1.2.9   misho     249:        pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7   misho     250:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    251:                if (array_Get(prg->prog_fds, i) && 
1.1.2.11  misho     252: #ifdef POPEN_STREAM
1.1.2.7   misho     253:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.11  misho     254: #else
                    255:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t))))
                    256: #endif
1.1.2.9   misho     257:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
                    258:                                clrbit(prg->prog_used, i);
1.1.2.7   misho     259:                                ret++;
1.1.2.9   misho     260:                        }
                    261:        pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7   misho     262: 
                    263:        return ret;
                    264: }
1.1.2.9   misho     265: 
                    266: /*
                    267:  * io_progAttach() - Attach to open program
                    268:  *
                    269:  * @prg = program pool
                    270:  * return: NULL error or !=NULL attached program handle
                    271:  */
1.1.2.11  misho     272: #ifdef POPEN_STREAM
1.1.2.9   misho     273: FILE *
1.1.2.11  misho     274: #else
                    275: int
                    276: #endif
1.1.2.9   misho     277: io_progAttach(prog_t * __restrict prg)
                    278: {
1.1.2.11  misho     279: #ifdef POPEN_STREAM
1.1.2.9   misho     280:        FILE *f = NULL;
1.1.2.11  misho     281: #else
                    282:        int f = -1;
                    283: #endif
1.1.2.9   misho     284:        register int i;
                    285: 
                    286:        if (!prg)
1.1.2.11  misho     287: #ifdef POPEN_STREAM
1.1.2.9   misho     288:                return NULL;
1.1.2.11  misho     289: #else
                    290:                return -1;
                    291: #endif
1.1.2.9   misho     292: 
                    293:        pthread_mutex_lock(&prg->prog_mtx);
                    294:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    295:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
                    296:                        setbit(prg->prog_used, i);
1.1.2.11  misho     297: #ifdef POPEN_STREAM
1.1.2.9   misho     298:                        f = array(prg->prog_fds, i, FILE*);
1.1.2.11  misho     299: #else
                    300:                        f = array(prg->prog_fds, i, intptr_t);
                    301: #endif
1.1.2.9   misho     302:                        break;
                    303:                }
                    304:        pthread_mutex_unlock(&prg->prog_mtx);
                    305: 
                    306:        return f;
                    307: }
                    308: 
                    309: /*
                    310:  * io_progDetach() - Detch from open program
                    311:  *
                    312:  * @prg= program pool
                    313:  * @pfd = attached program handle
                    314:  * return: none
                    315:  */
                    316: void
1.1.2.11  misho     317: #ifdef POPEN_STREAM
1.1.2.9   misho     318: io_progDetach(prog_t * __restrict prg, FILE *pfd)
1.1.2.11  misho     319: #else
                    320: io_progDetach(prog_t * __restrict prg, int pfd)
                    321: #endif
1.1.2.9   misho     322: {
                    323:        register int i;
                    324: 
                    325:        if (!prg || !pfd)
                    326:                return;
                    327: 
                    328:        pthread_mutex_lock(&prg->prog_mtx);
                    329:        for (i = 0; i < array_Size(prg->prog_fds); i++)
1.1.2.11  misho     330: #ifdef POPEN_STREAM
1.1.2.9   misho     331:                if (array(prg->prog_fds, i, FILE*) == pfd) {
1.1.2.11  misho     332: #else
                    333:                if (array(prg->prog_fds, i, intptr_t) == pfd) {
                    334: #endif
1.1.2.9   misho     335:                        clrbit(prg->prog_used, i);
                    336:                        break;
                    337:                }
                    338:        pthread_mutex_unlock(&prg->prog_mtx);
                    339: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>