mirror of
				https://git.haproxy.org/git/haproxy.git/
				synced 2025-10-31 00:21:00 +01:00 
			
		
		
		
	New specialized service to daily handle the update of download file without interruption of service and to be preemptively started before HAProxy. It consists on a standalone utility which shared a memory block with the DeviceAtlas module which handles the JSON data file update on a daily basis. Signed-off-by: David Carlier <dcarlier@deviceatlas.com>
		
			
				
	
	
		
			196 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			196 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #define _GNU_SOURCE
 | |
| #include <dac.h>
 | |
| #include <dadwcurl.h>
 | |
| #include <dadwarc.h>
 | |
| #include <getopt.h>
 | |
| #include <stdlib.h>
 | |
| #include <signal.h>
 | |
| #include <errno.h>
 | |
| #include <fcntl.h>
 | |
| #include <sys/mman.h>
 | |
| 
 | |
| #define ATLASTOKSZ PATH_MAX
 | |
| #define ATLASMAPNM "/hapdeviceatlas"
 | |
| 
 | |
| const char *__pgname;
 | |
| 
 | |
| static struct {
 | |
| 	da_dwatlas_t o;
 | |
| 	int ofd;
 | |
| 	void* atlasmap;
 | |
| } global_deviceatlassch = {
 | |
| 	.ofd = -1,
 | |
| 	.atlasmap = NULL
 | |
| };
 | |
| 
 | |
| 
 | |
| void usage(void)
 | |
| {
 | |
| 	fprintf(stderr, "%s -u download URL [-d hour (in H:M:S format) current hour by default] [-p path for the downloaded file, /tmp by default]\n", __pgname);
 | |
| 	exit(EXIT_FAILURE);
 | |
| }
 | |
| 
 | |
| static size_t jsonread(void *ctx, size_t count, char *buf)
 | |
| {
 | |
| 	return fread(buf, 1, count, ctx);
 | |
| }
 | |
| 
 | |
| static da_status_t jsonseek(void *ctx, off_t pos)
 | |
| {
 | |
| 	return fseek(ctx, pos, SEEK_SET) != -1 ? DA_OK : DA_SYS;
 | |
| }
 | |
| 
 | |
| static void dadwlog(dw_config_t cfg, const char* msg)
 | |
| {
 | |
| 	time_t now = time(NULL);
 | |
| 	char buf[26] = {0};
 | |
| 	ctime_r(&now, buf);
 | |
| 	buf[24] = 0;
 | |
| 	fprintf(stderr, "%s: %s\n", buf, msg);
 | |
| }
 | |
| 
 | |
| static dw_status_t dadwnot(void *a, dw_config_t *cfg)
 | |
| {
 | |
| 	da_dwatlas_t *o = (da_dwatlas_t *)a;
 | |
| 	if (!o)
 | |
| 		return DW_ERR;
 | |
| 	char *e;
 | |
| 	char jsondbuf[26] = {0}, buf[26] = {0}, atlasp[ATLASTOKSZ] = {0};
 | |
| 	time_t now = time(NULL);
 | |
| 	time_t jsond;
 | |
| 	int fd = -1;
 | |
| 	(void)a;
 | |
| 	jsond = da_getdatacreation(&o->atlas);
 | |
| 	dwgetfinalp(o->dcfg.info, atlasp, sizeof(atlasp));
 | |
| 	ctime_r(&jsond, jsondbuf);
 | |
| 	ctime_r(&now, buf);
 | |
| 	jsondbuf[24] = 0;
 | |
| 	buf[24] = 0;
 | |
| 
 | |
| 	printf("%s: data file generated on `%s`\n", buf, jsondbuf);
 | |
| 	int val = 1;
 | |
| 	unsigned char *ptr = (unsigned char *)global_deviceatlassch.atlasmap;
 | |
| 	memset(ptr, 0, sizeof(atlasp));
 | |
| 	strcpy(ptr, atlasp);
 | |
| 	return DW_OK;
 | |
| }
 | |
| 
 | |
| static da_status_t dadwinit(void)
 | |
| {
 | |
| 	if ((global_deviceatlassch.ofd = shm_open(ATLASMAPNM, O_RDWR | O_CREAT, 0660)) == -1) {
 | |
| 		fprintf(stderr, "%s\n", strerror(errno));
 | |
| 		return DA_SYS;
 | |
| 	}
 | |
| 
 | |
| 	if (ftruncate(global_deviceatlassch.ofd, ATLASTOKSZ) == -1) {
 | |
| 		close(global_deviceatlassch.ofd);
 | |
| 		return DA_SYS;
 | |
| 	}
 | |
| 	lseek(global_deviceatlassch.ofd, 0, SEEK_SET);
 | |
| 	global_deviceatlassch.atlasmap = mmap(0, ATLASTOKSZ, PROT_READ | PROT_WRITE, MAP_SHARED, global_deviceatlassch.ofd, 0);
 | |
| 	if (global_deviceatlassch.atlasmap == MAP_FAILED) {
 | |
| 		fprintf(stderr, "%s\n", strerror(errno));
 | |
| 		return DA_SYS;
 | |
| 	} else {
 | |
| 		memset(global_deviceatlassch.atlasmap, 0, ATLASTOKSZ);
 | |
| 		return DA_OK;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void dadwexit(int sig __attribute__((unused)), siginfo_t *s __attribute__((unused)), void *ctx __attribute__((unused)))
 | |
| {
 | |
| 	ssize_t w;
 | |
| 
 | |
| 	fprintf(stderr, "%s: exit\n", __pgname);
 | |
| 	dw_daatlas_close(&global_deviceatlassch.o);
 | |
| 	da_fini();
 | |
| 	munmap(global_deviceatlassch.atlasmap, ATLASTOKSZ);
 | |
| 	close(global_deviceatlassch.ofd);
 | |
| 	shm_unlink(ATLASMAPNM);
 | |
| 	exit(EXIT_SUCCESS);
 | |
| }
 | |
| 
 | |
| int main(int argc, char **argv)
 | |
| {
 | |
| 	const char *opts = "u:p:d:h";
 | |
| 	bool dset = false;
 | |
| 	size_t i;
 | |
| 	int ch;
 | |
| 
 | |
| 	da_property_decl_t extraprops[1] = {
 | |
| 		{ 0, 0 }
 | |
| 	};
 | |
| 
 | |
| 	__pgname = argv[0];
 | |
| 
 | |
| 	dw_df_dainit_fn = curldwinit;
 | |
| 	dw_df_dacleanup_fn = curldwcleanup;
 | |
| 
 | |
| 	da_init();
 | |
| 	memset(&global_deviceatlassch.o.dcfg, 0, sizeof(global_deviceatlassch.o.dcfg));
 | |
| 	while ((ch = getopt(argc, argv, opts)) != -1) {
 | |
| 		switch (ch) {
 | |
| 		case 'u':
 | |
| 			global_deviceatlassch.o.dcfg.info.url = strdup(optarg);
 | |
| 			break;
 | |
| 		case 'p':
 | |
| 			global_deviceatlassch.o.dcfg.info.path = strdup(optarg);
 | |
| 			break;
 | |
| 		case 'd':
 | |
| 			if (strptime(optarg, "%H:%M:%S", &global_deviceatlassch.o.dcfg.info.rtm) != NULL)
 | |
| 				dset = true;
 | |
| 			else
 | |
| 				usage();
 | |
| 			break;
 | |
| 		case 'h':
 | |
| 		default:
 | |
| 			usage();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (!dset) {
 | |
| 		time_t now = time(NULL);
 | |
| 		struct tm *cnow = gmtime(&now);
 | |
| 		memcpy(&global_deviceatlassch.o.dcfg.info.rtm, cnow, offsetof(struct tm, tm_mday));
 | |
| 	}
 | |
| 
 | |
| 	if (!global_deviceatlassch.o.dcfg.info.url)
 | |
| 		usage();
 | |
| 
 | |
| 	struct sigaction sa;
 | |
| 	memset(&sa, 0, sizeof(sa));
 | |
| 	sa.sa_flags = SA_SIGINFO | SA_RESTART;
 | |
| 	sa.sa_sigaction = dadwexit;
 | |
| 
 | |
| 	global_deviceatlassch.o.dcfg.info.datatm = 1;
 | |
| 	global_deviceatlassch.o.dcfg.info.chksum = 1;
 | |
| 	global_deviceatlassch.o.dcfg.info.reload = 1;
 | |
| 	global_deviceatlassch.o.dcfg.info.tobin = 1;
 | |
| 	global_deviceatlassch.o.dcfg.ep = extraprops;
 | |
| 	global_deviceatlassch.o.dcfg.dwproc = curldwproc;
 | |
| 	global_deviceatlassch.o.dcfg.dwextract = dadwextract;
 | |
| 	global_deviceatlassch.o.dcfg.lptr = (void *)stderr;
 | |
| 	global_deviceatlassch.o.dcfg.dwlog = &dadwlog;
 | |
| 	global_deviceatlassch.o.dcfg.dwnotify_n = &dadwnot;
 | |
| 	global_deviceatlassch.o.rfn = jsonread;
 | |
| 	global_deviceatlassch.o.posfn = jsonseek;
 | |
| 
 | |
| 	if (dadwinit() != DA_OK) {
 | |
| 		fprintf(stderr, "%s init failed\n", __pgname);
 | |
| 		exit(EXIT_FAILURE);
 | |
| 	}
 | |
| 
 | |
| 	if (da_atlas_open_schedule(&global_deviceatlassch.o) != DA_OK) {
 | |
| 		fprintf(stderr, "%s scheduling failed\n", __pgname);
 | |
| 		exit(EXIT_FAILURE);
 | |
| 	}
 | |
| 
 | |
| 	sigaction(SIGINT, &sa, NULL);
 | |
| 	sigaction(SIGQUIT, &sa, NULL);
 | |
| 	sigaction(SIGTERM, &sa, NULL);
 | |
| 
 | |
| 	while (true) sleep(1);
 | |
| 
 | |
| 	return 0;
 | |
| }
 |