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

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);
                     74: 
                     75:        e_free(*pprg);
                     76:        *pprg = NULL;
                     77: }
                     78: 
                     79: /*
                     80:  * io_progClose() - Close all programs in pool
                     81:  *
                     82:  * @prg = program pool
                     83:  * @closeNum = close program(s) (0 all)
                     84:  * return: 0 error, >0 closed programs
                     85:  */
                     86: int
                     87: io_progClose(prog_t * __restrict prg, u_int closeNum)
                     88: {
                     89:        register int i;
                     90:        int ret = 0;
                     91: 
                     92:        if (!prg)
                     93:                return 0;
                     94:        if (closeNum > prg->prog_maxn) {
                     95:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                     96:                return 0;
                     97:        }
                     98: 
                     99:        pthread_mutex_lock(&prg->prog_mtx);
                    100:        for (i = array_Size(prg->prog_fds) - 1; 
                    101:                        (closeNum ? ret < closeNum : 42) && i > -1; i--)
                    102:                if (array_Get(prg->prog_fds, i)) {
1.1.2.11  misho     103: #ifdef POPEN_STREAM
1.1.2.6   misho     104:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     105: #else
                    106:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    107: #endif
1.1.2.1   misho     108:                        array_Del(prg->prog_fds, i, 0);
1.1.2.9   misho     109:                        clrbit(prg->prog_used, i);
1.1.2.1   misho     110:                        prg->prog_cnum--;
                    111:                        ret++;
                    112:                }
                    113:        pthread_mutex_unlock(&prg->prog_mtx);
                    114: 
                    115:        return ret;
                    116: }
                    117: 
                    118: /*
                    119:  * io_progOpen() - Execute number of program(s)
                    120:  *
                    121:  * @prg = program pool
                    122:  * @execNum = execute program(s) (0 max)
                    123:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
                    124:  */
                    125: int
                    126: io_progOpen(prog_t * __restrict prg, u_int execNum)
                    127: {
1.1.2.11  misho     128: #ifdef POPEN_STREAM
1.1.2.1   misho     129:        FILE *f;
1.1.2.11  misho     130: #else
                    131:        int f;
                    132: #endif
1.1.2.4   misho     133:        int stat, ret = 0;
1.1.2.1   misho     134:        register int i;
1.1.2.4   misho     135:        pid_t pid;
1.1.2.1   misho     136: 
                    137:        if (!prg)
                    138:                return 0;
1.1.2.8   misho     139:        if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1   misho     140:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    141:                return 0;
                    142:        }
                    143: 
                    144:        pthread_mutex_lock(&prg->prog_mtx);
                    145:        for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
                    146:                if (!array_Get(prg->prog_fds, i)) {
1.1.2.6   misho     147:                        f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.11  misho     148: #ifdef POPEN_STREAM
1.1.2.1   misho     149:                        if (!f) {
1.1.2.11  misho     150: #else
                    151:                        if (f == -1) {
                    152: #endif
1.1.2.1   misho     153:                                LOGERR;
1.1.2.5   misho     154:                                ret = -1;
1.1.2.1   misho     155:                                break;
1.1.2.6   misho     156:                        } else if (waitpid(pid, &stat, WNOHANG)) {
                    157:                                io_SetErr(ECHILD, "Program with pid=%d exit with status %d", 
                    158:                                                pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.5   misho     159:                                ret = -1;
1.1.2.4   misho     160:                                break;
1.1.2.1   misho     161:                        } else
                    162:                                array_Set(prg->prog_fds, i, f);
                    163:                        prg->prog_cnum++;
                    164:                        ret++;
                    165:                }
                    166:        pthread_mutex_unlock(&prg->prog_mtx);
                    167: 
                    168:        return ret;
                    169: }
                    170: 
                    171: /*
1.1.2.8   misho     172:  * io_progGrow() - Execute to number of programs in pool
                    173:  *
                    174:  * @prg = program pool
                    175:  * @toNum = execute to number of programs (0 max)
                    176:  * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
                    177:  */
                    178: int
                    179: io_progGrow(prog_t * __restrict prg, u_int toNum)
                    180: {
                    181:        if (!prg)
                    182:                return 0;
                    183:        if (toNum > prg->prog_maxn) {
                    184:                io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
                    185:                return 0;
                    186:        }
                    187:        if (!toNum)
                    188:                toNum = prg->prog_maxn;
                    189: 
                    190:        return io_progOpen(prg, toNum - prg->prog_cnum);
                    191: }
                    192: 
                    193: /*
1.1.2.1   misho     194:  * io_progVacuum() - Vacuum pool to running number of programs
                    195:  *
                    196:  * @prg = program pool
                    197:  * @toNum = vacuum to number of programs (0 to init number)
                    198:  * return: 0 error or >0 closed programs
                    199:  */
                    200: int
                    201: io_progVacuum(prog_t * __restrict prg, u_int toNum)
                    202: {
                    203:        register int i;
                    204:        int ret = 0;
                    205: 
                    206:        if (!prg)
                    207:                return 0;
                    208:        if (toNum > prg->prog_maxn) {
                    209:                io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
                    210:                return 0;
                    211:        }
                    212:        if (!toNum)
                    213:                toNum = prg->prog_inin;
                    214: 
                    215:        pthread_mutex_lock(&prg->prog_mtx);
                    216:        for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.10  misho     217:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
1.1.2.11  misho     218: #ifdef POPEN_STREAM
1.1.2.6   misho     219:                        e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.11  misho     220: #else
                    221:                        e_pclose((int) array(prg->prog_fds, i, intptr_t));
                    222: #endif
1.1.2.1   misho     223:                        array_Del(prg->prog_fds, i, 0);
                    224:                        prg->prog_cnum--;
                    225:                        ret++;
                    226:                }
                    227:        pthread_mutex_unlock(&prg->prog_mtx);
                    228: 
                    229:        return ret;
                    230: }
1.1.2.7   misho     231: 
                    232: /*
                    233:  * io_progCheck() - Check exit status of program pool
                    234:  *
                    235:  * @prg = program pool
                    236:  * return: -1 error or >-1 exited programs
                    237:  */
                    238: int
                    239: io_progCheck(prog_t * __restrict prg)
                    240: {
                    241:        int ret = 0;
                    242:        struct tagPIOPID *p;
                    243:        register int i;
                    244: 
                    245:        if (!prg)
                    246:                return -1;
                    247: 
1.1.2.9   misho     248:        pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7   misho     249:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    250:                if (array_Get(prg->prog_fds, i) && 
1.1.2.11  misho     251: #ifdef POPEN_STREAM
1.1.2.7   misho     252:                                (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.11  misho     253: #else
                    254:                                (p = pio_pgetpid((int) array(prg->prog_fds, i, intptr_t))))
                    255: #endif
1.1.2.9   misho     256:                        if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
                    257:                                clrbit(prg->prog_used, i);
1.1.2.7   misho     258:                                ret++;
1.1.2.9   misho     259:                        }
                    260:        pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7   misho     261: 
                    262:        return ret;
                    263: }
1.1.2.9   misho     264: 
                    265: /*
                    266:  * io_progAttach() - Attach to open program
                    267:  *
                    268:  * @prg = program pool
                    269:  * return: NULL error or !=NULL attached program handle
                    270:  */
1.1.2.11  misho     271: #ifdef POPEN_STREAM
1.1.2.9   misho     272: FILE *
1.1.2.11  misho     273: #else
                    274: int
                    275: #endif
1.1.2.9   misho     276: io_progAttach(prog_t * __restrict prg)
                    277: {
1.1.2.11  misho     278: #ifdef POPEN_STREAM
1.1.2.9   misho     279:        FILE *f = NULL;
1.1.2.11  misho     280: #else
                    281:        int f = -1;
                    282: #endif
1.1.2.9   misho     283:        register int i;
                    284: 
                    285:        if (!prg)
1.1.2.11  misho     286: #ifdef POPEN_STREAM
1.1.2.9   misho     287:                return NULL;
1.1.2.11  misho     288: #else
                    289:                return -1;
                    290: #endif
1.1.2.9   misho     291: 
                    292:        pthread_mutex_lock(&prg->prog_mtx);
                    293:        for (i = 0; i < array_Size(prg->prog_fds); i++)
                    294:                if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
                    295:                        setbit(prg->prog_used, i);
1.1.2.11  misho     296: #ifdef POPEN_STREAM
1.1.2.9   misho     297:                        f = array(prg->prog_fds, i, FILE*);
1.1.2.11  misho     298: #else
                    299:                        f = array(prg->prog_fds, i, intptr_t);
                    300: #endif
1.1.2.9   misho     301:                        break;
                    302:                }
                    303:        pthread_mutex_unlock(&prg->prog_mtx);
                    304: 
                    305:        return f;
                    306: }
                    307: 
                    308: /*
                    309:  * io_progDetach() - Detch from open program
                    310:  *
                    311:  * @prg= program pool
                    312:  * @pfd = attached program handle
                    313:  * return: none
                    314:  */
                    315: void
1.1.2.11  misho     316: #ifdef POPEN_STREAM
1.1.2.9   misho     317: io_progDetach(prog_t * __restrict prg, FILE *pfd)
1.1.2.11  misho     318: #else
                    319: io_progDetach(prog_t * __restrict prg, int pfd)
                    320: #endif
1.1.2.9   misho     321: {
                    322:        register int i;
                    323: 
                    324:        if (!prg || !pfd)
                    325:                return;
                    326: 
                    327:        pthread_mutex_lock(&prg->prog_mtx);
                    328:        for (i = 0; i < array_Size(prg->prog_fds); i++)
1.1.2.11  misho     329: #ifdef POPEN_STREAM
1.1.2.9   misho     330:                if (array(prg->prog_fds, i, FILE*) == pfd) {
1.1.2.11  misho     331: #else
                    332:                if (array(prg->prog_fds, i, intptr_t) == pfd) {
                    333: #endif
1.1.2.9   misho     334:                        clrbit(prg->prog_used, i);
                    335:                        break;
                    336:                }
                    337:        pthread_mutex_unlock(&prg->prog_mtx);
                    338: }

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