Annotation of libaitio/src/exec.c, revision 1.1.2.9
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.2 misho 48:
1.1.2.6 misho 49: if (io_progOpen(prg, prg->prog_inin) < 0) {
1.1.2.2 misho 50: io_progDestroy(&prg);
1.1.2.6 misho 51: prg = NULL;
52: }
1.1.2.1 misho 53: return prg;
54: }
55:
56: /*
57: * io_progDestroy() - Destroy entire program pool
58: *
59: * @pprg = program pool
60: * return: none
61: */
62: void
63: io_progDestroy(prog_t ** __restrict pprg)
64: {
65: if (!pprg || !*pprg)
66: return;
67:
68: io_progClose(*pprg, 0);
69:
1.1.2.9 ! misho 70: e_free((*pprg)->prog_used);
1.1.2.1 misho 71: array_Destroy(&(*pprg)->prog_fds);
72: pthread_mutex_destroy(&(*pprg)->prog_mtx);
73:
74: e_free(*pprg);
75: *pprg = NULL;
76: }
77:
78: /*
79: * io_progClose() - Close all programs in pool
80: *
81: * @prg = program pool
82: * @closeNum = close program(s) (0 all)
83: * return: 0 error, >0 closed programs
84: */
85: int
86: io_progClose(prog_t * __restrict prg, u_int closeNum)
87: {
88: register int i;
89: int ret = 0;
90:
91: if (!prg)
92: return 0;
93: if (closeNum > prg->prog_maxn) {
94: io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
95: return 0;
96: }
97:
98: pthread_mutex_lock(&prg->prog_mtx);
99: for (i = array_Size(prg->prog_fds) - 1;
100: (closeNum ? ret < closeNum : 42) && i > -1; i--)
101: if (array_Get(prg->prog_fds, i)) {
1.1.2.6 misho 102: e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.1 misho 103: array_Del(prg->prog_fds, i, 0);
1.1.2.9 ! misho 104: clrbit(prg->prog_used, i);
1.1.2.1 misho 105: prg->prog_cnum--;
106: ret++;
107: }
108: pthread_mutex_unlock(&prg->prog_mtx);
109:
110: return ret;
111: }
112:
113: /*
114: * io_progOpen() - Execute number of program(s)
115: *
116: * @prg = program pool
117: * @execNum = execute program(s) (0 max)
118: * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
119: */
120: int
121: io_progOpen(prog_t * __restrict prg, u_int execNum)
122: {
123: FILE *f;
1.1.2.4 misho 124: int stat, ret = 0;
1.1.2.1 misho 125: register int i;
1.1.2.4 misho 126: pid_t pid;
1.1.2.1 misho 127:
128: if (!prg)
129: return 0;
1.1.2.8 misho 130: if (prg->prog_cnum + execNum > prg->prog_maxn) {
1.1.2.1 misho 131: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
132: return 0;
133: }
134:
135: pthread_mutex_lock(&prg->prog_mtx);
136: for (i = 0; (execNum ? ret < execNum : 42) && i < array_Size(prg->prog_fds); i++)
137: if (!array_Get(prg->prog_fds, i)) {
1.1.2.6 misho 138: f = e_popen(prg->prog_name, "r+", &pid);
1.1.2.1 misho 139: if (!f) {
140: LOGERR;
1.1.2.5 misho 141: ret = -1;
1.1.2.1 misho 142: break;
1.1.2.6 misho 143: } else if (waitpid(pid, &stat, WNOHANG)) {
144: io_SetErr(ECHILD, "Program with pid=%d exit with status %d",
145: pid, WIFEXITED(stat) ? WEXITSTATUS(stat) : -1);
1.1.2.5 misho 146: ret = -1;
1.1.2.4 misho 147: break;
1.1.2.1 misho 148: } else
149: array_Set(prg->prog_fds, i, f);
150: prg->prog_cnum++;
151: ret++;
152: }
153: pthread_mutex_unlock(&prg->prog_mtx);
154:
155: return ret;
156: }
157:
158: /*
1.1.2.8 misho 159: * io_progGrow() - Execute to number of programs in pool
160: *
161: * @prg = program pool
162: * @toNum = execute to number of programs (0 max)
163: * return: 0 error, >0 executed programs and abs(<0) executed programs with logged error
164: */
165: int
166: io_progGrow(prog_t * __restrict prg, u_int toNum)
167: {
168: if (!prg)
169: return 0;
170: if (toNum > prg->prog_maxn) {
171: io_SetErr(EINVAL, "Requested number for program execution is over pool's limit");
172: return 0;
173: }
174: if (!toNum)
175: toNum = prg->prog_maxn;
176:
177: return io_progOpen(prg, toNum - prg->prog_cnum);
178: }
179:
180: /*
1.1.2.1 misho 181: * io_progVacuum() - Vacuum pool to running number of programs
182: *
183: * @prg = program pool
184: * @toNum = vacuum to number of programs (0 to init number)
185: * return: 0 error or >0 closed programs
186: */
187: int
188: io_progVacuum(prog_t * __restrict prg, u_int toNum)
189: {
190: register int i;
191: int ret = 0;
192:
193: if (!prg)
194: return 0;
195: if (toNum > prg->prog_maxn) {
196: io_SetErr(EINVAL, "Requested number for close program is over pool's limit");
197: return 0;
198: }
199: if (!toNum)
200: toNum = prg->prog_inin;
201:
202: pthread_mutex_lock(&prg->prog_mtx);
203: for (i = array_Size(prg->prog_fds) - 1; prg->prog_cnum > toNum && i > -1; i--)
1.1.2.9 ! misho 204: if (array_Get(prg->prog_fds, i) && isset(prg->prog_used, i)) {
1.1.2.6 misho 205: e_pclose(array(prg->prog_fds, i, FILE*));
1.1.2.1 misho 206: array_Del(prg->prog_fds, i, 0);
1.1.2.9 ! misho 207: clrbit(prg->prog_used, i);
1.1.2.1 misho 208: prg->prog_cnum--;
209: ret++;
210: }
211: pthread_mutex_unlock(&prg->prog_mtx);
212:
213: return ret;
214: }
1.1.2.7 misho 215:
216: /*
217: * io_progCheck() - Check exit status of program pool
218: *
219: * @prg = program pool
220: * return: -1 error or >-1 exited programs
221: */
222: int
223: io_progCheck(prog_t * __restrict prg)
224: {
225: int ret = 0;
226: struct tagPIOPID *p;
227: register int i;
228:
229: if (!prg)
230: return -1;
231:
1.1.2.9 ! misho 232: pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7 misho 233: for (i = 0; i < array_Size(prg->prog_fds); i++)
234: if (array_Get(prg->prog_fds, i) &&
235: (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.9 ! misho 236: if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
! 237: clrbit(prg->prog_used, i);
1.1.2.7 misho 238: ret++;
1.1.2.9 ! misho 239: }
! 240: pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7 misho 241:
242: return ret;
243: }
1.1.2.9 ! misho 244:
! 245: /*
! 246: * io_progAttach() - Attach to open program
! 247: *
! 248: * @prg = program pool
! 249: * return: NULL error or !=NULL attached program handle
! 250: */
! 251: FILE *
! 252: io_progAttach(prog_t * __restrict prg)
! 253: {
! 254: FILE *f = NULL;
! 255: register int i;
! 256:
! 257: if (!prg)
! 258: return NULL;
! 259:
! 260: pthread_mutex_lock(&prg->prog_mtx);
! 261: for (i = 0; i < array_Size(prg->prog_fds); i++)
! 262: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
! 263: setbit(prg->prog_used, i);
! 264: f = array(prg->prog_fds, i, FILE*);
! 265: break;
! 266: }
! 267: pthread_mutex_unlock(&prg->prog_mtx);
! 268:
! 269: return f;
! 270: }
! 271:
! 272: /*
! 273: * io_progDetach() - Detch from open program
! 274: *
! 275: * @prg= program pool
! 276: * @pfd = attached program handle
! 277: * return: none
! 278: */
! 279: void
! 280: io_progDetach(prog_t * __restrict prg, FILE *pfd)
! 281: {
! 282: register int i;
! 283:
! 284: if (!prg || !pfd)
! 285: return;
! 286:
! 287: pthread_mutex_lock(&prg->prog_mtx);
! 288: for (i = 0; i < array_Size(prg->prog_fds); i++)
! 289: if (array(prg->prog_fds, i, FILE*) == pfd) {
! 290: clrbit(prg->prog_used, i);
! 291: break;
! 292: }
! 293: pthread_mutex_unlock(&prg->prog_mtx);
! 294: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>