]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: da: new optional data file download scheduler service.
authorDavid Carlier <dcarlier@deviceatlas.com>
Fri, 21 Jan 2022 20:46:40 +0000 (20:46 +0000)
committerWilly Tarreau <w@1wt.eu>
Fri, 28 Jan 2022 06:23:07 +0000 (07:23 +0100)
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>
addons/deviceatlas/Makefile [new file with mode: 0644]
addons/deviceatlas/dadwsch.c [new file with mode: 0644]

diff --git a/addons/deviceatlas/Makefile b/addons/deviceatlas/Makefile
new file mode 100644 (file)
index 0000000..fbcffca
--- /dev/null
@@ -0,0 +1,48 @@
+# DEVICEATLAS_SRC     : DeviceAtlas API source root path
+
+
+OS              := $(shell uname -s)
+OBJS            := dadwsch.o
+CFLAGS          := -g -O2
+LDFLAGS         :=
+
+CURL_CONFIG     := curl-config
+CURLDIR         := $(shell $(CURL_CONFIG) --prefix 2>/dev/null || echo /usr/local)
+CURL_INC        := $(CURLDIR)/include
+CURL_LIB        := $(CURLDIR)/lib
+CURL_LDFLAGS    := $(shell $(CURL_CONFIG) --libs 2>/dev/null || echo -L /usr/local/lib -lcurl)
+
+PCRE2_CONFIG    := pcre2-config
+PCRE2DIR        := $(shell $(PCRE2_CONFIG) --prefix 2>/dev/null || echo /usr/local)
+PCRE2_INC       := $(PCRE2DIR)/include
+PCRE2_LIB       := $(PCRE2DIR)/lib
+PCRE2_LDFLAGS   := $(shell $(PCRE2_CONFIG) --libs8 2>/dev/null || echo /usr/local)
+
+ifeq ($(DEVICEATLAS_SRC),)
+dadwsch:    dadwsch.c
+       $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+LDFLAGS         += -lda
+else
+DEVICEATLAS_INC = $(DEVICEATLAS_SRC)
+DEVICEATLAS_LIB = $(DEVICEATLAS_SRC)
+CFLAGS          += -DDA_REGEX_HDR=\"dac_pcre2.c\" -DDA_REGEX_TAG=2
+CFLAGS          += -DMOBI_CURL -DMOBI_CURLSSET -DMOBI_GZ -DMOBI_ZIP
+CFLAGS          += -I$(DEVICEATLAS_INC) -I$(CURL_INC) -I$(PCRE2DIR)
+LDFLAGS         += $(CURL_LDFLAGS) $(PCRE2_LDFLAGS) -lz -lzip -lpthread
+
+dadwsch:    dadwsch.c $(DEVICEATLAS_SRC)/dac.c $(DEVICEATLAS_SRC)/dasch.c $(DEVICEATLAS_SRC)/dadwarc.c $(DEVICEATLAS_SRC)/dadwcom.c $(DEVICEATLAS_SRC)/dadwcurl.c $(DEVICEATLAS_SRC)/json.c $(DEVICEATLAS_SRC)/Os/daunix.c
+       $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+endif
+
+ifeq ($(OS), Linux)
+LDFLAGS         += -lrt
+endif
+ifeq ($(OS), SunOS)
+LDFLAGS         += -lrt
+endif
+
+clean:
+               rm -f *.o
+               rm -f $(DEVICEATLAS_LIB)*.o
+               rm -f dadwsch
diff --git a/addons/deviceatlas/dadwsch.c b/addons/deviceatlas/dadwsch.c
new file mode 100644 (file)
index 0000000..e35566a
--- /dev/null
@@ -0,0 +1,195 @@
+#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;
+}