toolbox

Check-in [7780f9a20b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:radios-check: use <sys/queue.h> + job management cleanup
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:7780f9a20b10cd1e9bb8d79e51ac523bc51c6a231ebe48a38b2755cf3c1eab52
User & Date: jef 2019-04-15 20:12:36
Context
2019-04-15
20:36
radios-check: fix memmove index check-in: e75c5886d3 user: jef tags: trunk
20:12
radios-check: use <sys/queue.h> + job management cleanup check-in: 7780f9a20b user: jef tags: trunk
2019-04-14
15:27
radio: fix broken streams check-in: 0ec0037646 user: jef tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/radios-check/radios-check.c.

3
4
5
6
7
8
9

10
11
12
13
14
15
16
..
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
...
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
...
214
215
216
217
218
219
220

221
222
223
224
225
226
227
...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243


244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267













268
269










270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <poll.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "cJSON.h"
#include "die.h"
#include "xmalloc.h"

#define PROGNAME "radios-check"
#define URL_RADIOS_LIST "https://foutaise.org/api/radios/list"

................................................................................
};

struct job {
	struct radio *radio;
	pid_t pid;
	int fd;
	struct job_res {
		size_t id;
		int ok;
	} res;
};

struct radio {
	char *name;
	char *stream;
	int ok;

};

struct radios {
	size_t cap;
	size_t grow;
	size_t size;
	struct radio **radios;
};

struct radio_status {
	CURL *curl;
	struct radio *radio;
};

void
................................................................................
		"	%s\n"
		"Options:\n"
		"	-h : display this help and exit\n", PROGNAME);
	exit(1);
}

struct radios*
radios_new(size_t grow)
{
	struct radios *radios = xcalloc(1, sizeof(struct radios));
	radios->grow = grow;
	radios->cap = grow;
	radios->size = 0;
	radios->radios = xcalloc(radios->cap, sizeof(struct radio *));



	return radios;
}

void
radios_add(struct radios *radios, struct radio *radio)
{
	if (radios->size == radios->cap) {
		radios->cap += radios->grow;
		radios->radios = xrealloc(radios->radios, radios->cap * sizeof(struct radio *));
	}
	radios->radios[radios->size++] = radio;
}

void
radios_free(struct radios *radios)
{
	struct radio *radio;
	size_t i;


	for (i = 0; i < radios->size; i++) {
		radio = radios->radios[i];
		xfree(radio->name);
		xfree(radio->stream);
		xfree(radio);
	}
	xfree(radios);
}

................................................................................

	curl_do(URL_RADIOS_LIST, write_buffer_cb, &buffer);
	cJSON *json = cJSON_Parse(buffer.data);
	xfree(buffer.data);
	if (json == NULL)
		die("json parse error");

	radios = radios_new(10);
	cJSON *block;
	cJSON_ArrayForEach(block, json) {
		char *name = cJSON_GetObjectItem(block, "name")->valuestring;
		char *stream = cJSON_GetObjectItem(block, "stream")->valuestring;
		radio = xcalloc(1, sizeof(struct radio));
		radio->name = xstrdup(name);
		radio->stream = xstrdup(stream);
................................................................................
	switch (pid) {
	case -1:
		die("fork error");
		break;
	case 0:
		close(fds[0]);
		radio_set_status(job->radio);

		job->res.ok = job->radio->ok;
		towrite = sizeof(job->res);
		if (write(fds[1], &job->res, towrite) != towrite)
			die("write error");
		close(fds[1]);
		exit(0);
		break;
................................................................................

	close(fds[1]);
	job->fd = fds[0];
	job->pid = pid;
}

void
radios_pcheck(struct radios *radios)
{
	size_t nthreads = 20;
	struct job jobs[nthreads], job;
	struct pollfd fd[1];
	size_t i, nlaunched = 0, nrunning = 0;
	int status;
	pid_t pid;



	while (nlaunched < radios->size || nrunning > 0) {
		/* start new jobs */
		while (nrunning < nthreads && nlaunched < radios->size) {
			jobs[nrunning].radio = radios->radios[nlaunched];
			jobs[nrunning].res.id = nlaunched;
			job_run(&jobs[nrunning]);
			nlaunched++;
			nrunning++;
		}

		/* handle terminated jobs */
		while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
			for (i = 0; jobs[i].pid != pid; i++);
			job = jobs[i];
			fd[0].fd = job.fd;
			fd[0].events = POLLIN;
			if (poll(fd, 1, 0) > 0) {
				if (read(job.fd, &job.res, sizeof(job.res)) == sizeof(job.res)) {
					radios->radios[job.res.id]->ok = job.res.ok;
				}
			}
			close(job.fd);
			memmove(&jobs[i], &jobs[i+1], (nrunning - i) * sizeof(struct job));













			nrunning--;
		}










	}
}

void
radios_check()
{

	struct radios *radios;
	size_t i;

	radios = radios_get();
	radios_pcheck(radios);
	for (i = 0; i < radios->size; i++) {
		if (! radios->radios[i]->ok)
			puts(radios->radios[i]->name);
	}
	radios_free(radios);
}

int
main(int argc, char *argv[])
{







>







 







|








>


<
|
<
<
<
<







 







|

|
<
<
<
<

>
>






|
<
<
<
<






|
<
>
|
<







 







|







 







>







 







|

|
<
<
<


>
>

<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>






>

<



|
|
|







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
..
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43




44
45
46
47
48
49
50
..
56
57
58
59
60
61
62
63
64
65




66
67
68
69
70
71
72
73
74
75




76
77
78
79
80
81
82

83
84

85
86
87
88
89
90
91
...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
220
221
222
223
224
225
226
227
228
229



230
231
232
233
234











235
236
237
238
239
240
241
242
243

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
291
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <poll.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/queue.h>
#include "cJSON.h"
#include "die.h"
#include "xmalloc.h"

#define PROGNAME "radios-check"
#define URL_RADIOS_LIST "https://foutaise.org/api/radios/list"

................................................................................
};

struct job {
	struct radio *radio;
	pid_t pid;
	int fd;
	struct job_res {
		struct radio *radio;
		int ok;
	} res;
};

struct radio {
	char *name;
	char *stream;
	int ok;
	TAILQ_ENTRY(radio) next;
};


TAILQ_HEAD(radios, radio);





struct radio_status {
	CURL *curl;
	struct radio *radio;
};

void
................................................................................
		"	%s\n"
		"Options:\n"
		"	-h : display this help and exit\n", PROGNAME);
	exit(1);
}

struct radios*
radios_new()
{
	struct radios *radios;





	radios = xcalloc(1, sizeof(struct radios));
	TAILQ_INIT(radios);
	return radios;
}

void
radios_add(struct radios *radios, struct radio *radio)
{
	TAILQ_INSERT_TAIL(radios, radio, next);




}

void
radios_free(struct radios *radios)
{
	struct radio *radio;
	while (! TAILQ_EMPTY(radios)) {

		radio = TAILQ_FIRST(radios);
		TAILQ_REMOVE(radios, radio, next);

		xfree(radio->name);
		xfree(radio->stream);
		xfree(radio);
	}
	xfree(radios);
}

................................................................................

	curl_do(URL_RADIOS_LIST, write_buffer_cb, &buffer);
	cJSON *json = cJSON_Parse(buffer.data);
	xfree(buffer.data);
	if (json == NULL)
		die("json parse error");

	radios = radios_new();
	cJSON *block;
	cJSON_ArrayForEach(block, json) {
		char *name = cJSON_GetObjectItem(block, "name")->valuestring;
		char *stream = cJSON_GetObjectItem(block, "stream")->valuestring;
		radio = xcalloc(1, sizeof(struct radio));
		radio->name = xstrdup(name);
		radio->stream = xstrdup(stream);
................................................................................
	switch (pid) {
	case -1:
		die("fork error");
		break;
	case 0:
		close(fds[0]);
		radio_set_status(job->radio);
		job->res.radio = job->radio;
		job->res.ok = job->radio->ok;
		towrite = sizeof(job->res);
		if (write(fds[1], &job->res, towrite) != towrite)
			die("write error");
		close(fds[1]);
		exit(0);
		break;
................................................................................

	close(fds[1]);
	job->fd = fds[0];
	job->pid = pid;
}

void
job_wait(struct job *jobs, size_t size)
{
	size_t i;



	int status;
	pid_t pid;
	struct job job;
	struct pollfd fd[1];












	pid = waitpid(-1, &status, 0);
	for (i = 0; jobs[i].pid != pid; i++);
	job = jobs[i];
	fd[0].fd = job.fd;
	fd[0].events = POLLIN;
	if (poll(fd, 1, 0) > 0) {
		if (read(job.fd, &job.res, sizeof(job.res)) == sizeof(job.res))
			job.res.radio->ok = job.res.ok;
	}

	close(job.fd);
	memmove(jobs + i, jobs + i + 1, (size - i) * sizeof(struct job));
}

void
radios_pcheck(struct radios *radios)
{
	struct radio *radio;
	size_t nthreads = 20;
	struct job jobs[nthreads];
	size_t nrunning = 0;

	TAILQ_FOREACH(radio, radios, next) {
		if (nrunning >= nthreads) {
			job_wait(jobs, nthreads);
			nrunning--;
		}

		jobs[nrunning].radio = radio;
		job_run(&jobs[nrunning]);
		nrunning++;
	}

	/* wait for pending jobs */
	while (nrunning > 0) {
		job_wait(jobs, nthreads);
		nrunning--;
	}
}

void
radios_check()
{
	struct radio *radio;
	struct radios *radios;


	radios = radios_get();
	radios_pcheck(radios);
	TAILQ_FOREACH(radio, radios, next) {
		if (! radio->ok)
			puts(radio->name);
	}
	radios_free(radios);
}

int
main(int argc, char *argv[])
{