1 /*---------- defer and backlog files ----------*/
3 static void open_defer(void) {
8 defer= fopen(path_defer, "a+");
9 if (!defer) sysdie("could not open defer file %s", path_defer);
11 /* truncate away any half-written records */
13 xfstat_isreg(fileno(defer), &stab, path_defer, "newly opened defer file");
15 if (stab.st_size > LONG_MAX)
16 crash("defer file %s size is far too large", path_defer);
21 long orgsize= stab.st_size;
22 long truncto= stab.st_size;
24 if (!truncto) break; /* was only (if anything) one half-truncated record */
25 if (fseek(defer, truncto-1, SEEK_SET) < 0)
26 syscrash("seek in defer file %s while truncating partial", path_defer);
31 syscrash("failed read from defer file %s", path_defer);
33 crash("defer file %s shrank while we were checking it!", path_defer);
39 if (stab.st_size != truncto) {
40 warn("truncating half-record at end of defer file %s -"
41 " shrinking by %ld bytes from %ld to %ld",
42 path_defer, orgsize - truncto, orgsize, truncto);
45 sysdie("could not flush defer file %s", path_defer);
46 if (ftruncate(fileno(defer), truncto))
47 syscrash("could not truncate defer file %s", path_defer);
50 info("continuing existing defer file %s (%ld bytes)",
53 if (fseek(defer, truncto, SEEK_SET))
54 syscrash("could not seek to new end of defer file %s", path_defer);
57 static void close_defer(void) {
62 xfstat_isreg(fileno(defer), &stab, path_defer, "defer file");
64 if (fclose(defer)) sysdie("could not close defer file %s", path_defer);
69 char *backlog= xasprintf("%s_backlog_%lu.%lu", feedfile,
71 (unsigned long)stab.st_ino);
72 if (link(path_defer, backlog))
73 sysdie("could not install defer file %s as backlog file %s",
75 if (unlink(path_defer))
76 syscrash("could not unlink old defer link %s to backlog file %s",
81 if (until_backlog_nextscan < 0 ||
82 until_backlog_nextscan > backlog_retry_minperiods + 1)
83 until_backlog_nextscan= backlog_retry_minperiods + 1;
86 void poll_backlog_file(void) {
87 if (until_backlog_nextscan < 0) return;
88 if (until_backlog_nextscan-- > 0) return;
89 search_backlog_file();
92 static void search_backlog_file(void) {
93 /* returns non-0 iff there are any backlog files */
99 const char *oldest_path=0;
100 time_t oldest_mtime=0, now;
102 if (backlog_input_file) return;
106 r= glob(globpat_backlog, GLOB_ERR|GLOB_MARK|GLOB_NOSORT, 0, &gl);
110 sysdie("failed to expand backlog pattern %s", globpat_backlog);
112 die("out of memory expanding backlog pattern %s", globpat_backlog);
114 for (ui=0; ui<gl.gl_pathc; ui++) {
115 const char *path= gl.gl_pathv[ui];
117 if (strchr(path,'#') || strchr(path,'~')) {
118 dbg("backlog file search skipping %s", path);
121 r= stat(path, &stab);
123 syswarn("failed to stat backlog file %s", path);
126 if (!S_ISREG(stab.st_mode)) {
127 warn("backlog file %s is not a plain file (or link to one)", path);
130 if (!oldest_path || stab.st_mtime < oldest_mtime) {
132 oldest_mtime= stab.st_mtime;
135 case GLOB_NOMATCH: /* fall through */
138 syscrash("glob expansion of backlog pattern %s gave unexpected"
139 " nonzero (error?) return value %d", globpat_backlog, r);
143 dbg("backlog scan: none");
145 if (sms==sm_DROPPED) {
147 notice("feed dropped and our work is complete");
150 if (r && errno!=ENOENT)
151 syswarn("failed to unlink cli socket for old feed");
153 xunlink(path_lock, "lockfile for old feed");
156 until_backlog_nextscan= backlog_spontrescan_periods;
161 double age= difftime(now, oldest_mtime);
162 long age_deficiency= (backlog_retry_minperiods * period_seconds) - age;
164 if (age_deficiency <= 0) {
165 dbg("backlog scan: found age=%f deficiency=%ld oldest=%s",
166 age, age_deficiency, oldest_path);
168 backlog_input_file= open_input_file(oldest_path);
169 if (!backlog_input_file) {
170 warn("backlog file %s vanished as we opened it", oldest_path);
174 inputfile_reading_start(backlog_input_file);
175 until_backlog_nextscan= -1;
179 until_backlog_nextscan= age_deficiency / period_seconds;
181 if (backlog_spontrescan_periods >= 0 &&
182 until_backlog_nextscan > backlog_spontrescan_periods)
183 until_backlog_nextscan= backlog_spontrescan_periods;
185 dbg("backlog scan: young age=%f deficiency=%ld nextscan=%d oldest=%s",
186 age, age_deficiency, until_backlog_nextscan, oldest_path);