Annotation of libaitio/src/exec.c, revision 1.1.2.10
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.10! misho 204: if (array_Get(prg->prog_fds, i) && isclr(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);
207: prg->prog_cnum--;
208: ret++;
209: }
210: pthread_mutex_unlock(&prg->prog_mtx);
211:
212: return ret;
213: }
1.1.2.7 misho 214:
215: /*
216: * io_progCheck() - Check exit status of program pool
217: *
218: * @prg = program pool
219: * return: -1 error or >-1 exited programs
220: */
221: int
222: io_progCheck(prog_t * __restrict prg)
223: {
224: int ret = 0;
225: struct tagPIOPID *p;
226: register int i;
227:
228: if (!prg)
229: return -1;
230:
1.1.2.9 misho 231: pthread_mutex_lock(&prg->prog_mtx);
1.1.2.7 misho 232: for (i = 0; i < array_Size(prg->prog_fds); i++)
233: if (array_Get(prg->prog_fds, i) &&
234: (p = pio_pgetpid(array(prg->prog_fds, i, FILE*))))
1.1.2.9 misho 235: if (waitpid(p->pid, &p->stat, WNOHANG) > 0) {
236: clrbit(prg->prog_used, i);
1.1.2.7 misho 237: ret++;
1.1.2.9 misho 238: }
239: pthread_mutex_unlock(&prg->prog_mtx);
1.1.2.7 misho 240:
241: return ret;
242: }
1.1.2.9 misho 243:
244: /*
245: * io_progAttach() - Attach to open program
246: *
247: * @prg = program pool
248: * return: NULL error or !=NULL attached program handle
249: */
250: FILE *
251: io_progAttach(prog_t * __restrict prg)
252: {
253: FILE *f = NULL;
254: register int i;
255:
256: if (!prg)
257: return NULL;
258:
259: pthread_mutex_lock(&prg->prog_mtx);
260: for (i = 0; i < array_Size(prg->prog_fds); i++)
261: if (array_Get(prg->prog_fds, i) && isclr(prg->prog_used, i)) {
262: setbit(prg->prog_used, i);
263: f = array(prg->prog_fds, i, FILE*);
264: break;
265: }
266: pthread_mutex_unlock(&prg->prog_mtx);
267:
268: return f;
269: }
270:
271: /*
272: * io_progDetach() - Detch from open program
273: *
274: * @prg= program pool
275: * @pfd = attached program handle
276: * return: none
277: */
278: void
279: io_progDetach(prog_t * __restrict prg, FILE *pfd)
280: {
281: register int i;
282:
283: if (!prg || !pfd)
284: return;
285:
286: pthread_mutex_lock(&prg->prog_mtx);
287: for (i = 0; i < array_Size(prg->prog_fds); i++)
288: if (array(prg->prog_fds, i, FILE*) == pfd) {
289: clrbit(prg->prog_used, i);
290: break;
291: }
292: pthread_mutex_unlock(&prg->prog_mtx);
293: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>