| 282 | } |
| 283 | |
| 284 | static bool |
| 285 | load_state(plugin_state_t *pstate, invalidate_t **ilist) |
| 286 | { |
| 287 | if (NULL == *ilist) { |
| 288 | return true; |
| 289 | } |
| 290 | |
| 291 | FILE *const fs = fopen(pstate->state_path, "r"); |
| 292 | if (NULL == fs) { |
| 293 | Dbg(dbg_ctl, "Could not open state %s for reading", pstate->state_path); |
| 294 | return false; |
| 295 | } |
| 296 | |
| 297 | time_t const now = time(nullptr); |
| 298 | |
| 299 | const char *errptr; |
| 300 | int erroffset; |
| 301 | int ovector[OVECTOR_SIZE]; |
| 302 | pcre *const config_re = pcre_compile("^([^#].+?)\\s+(\\d+)\\s+(\\d+)\\s+(\\w+)\\s*$", 0, &errptr, &erroffset, nullptr); |
| 303 | TSReleaseAssert(nullptr != config_re); |
| 304 | |
| 305 | char line[LINE_MAX]; |
| 306 | int ln = 0; |
| 307 | while (fgets(line, LINE_MAX, fs) != nullptr) { |
| 308 | Dbg(dbg_ctl, "state: processing: %d %s", ln, line); |
| 309 | ++ln; |
| 310 | int const rc = pcre_exec(config_re, nullptr, line, strlen(line), 0, 0, ovector, OVECTOR_SIZE); |
| 311 | |
| 312 | if (5 == rc) { |
| 313 | invalidate_t *const inv = (invalidate_t *)TSmalloc(sizeof(invalidate_t)); |
| 314 | init_invalidate_t(inv); |
| 315 | |
| 316 | pcre_get_substring(line, ovector, rc, 1, &(inv->regex_text)); |
| 317 | inv->epoch = atoi(line + ovector[4]); |
| 318 | inv->expiry = atoi(line + ovector[6]); |
| 319 | |
| 320 | if (inv->expiry < now) { |
| 321 | Dbg(dbg_ctl, "state: skipping expired : '%s'", inv->regex_text); |
| 322 | free_invalidate_t(inv); |
| 323 | continue; |
| 324 | } |
| 325 | |
| 326 | int const len = ovector[9] - ovector[8]; |
| 327 | char const *const type = line + ovector[8]; |
| 328 | |
| 329 | if (0 == strncasecmp(type, RESULT_STALE, len)) { |
| 330 | Dbg(dbg_ctl, "state: regex line set to result type %s: '%s'", RESULT_STALE, inv->regex_text); |
| 331 | } else if (0 == strncasecmp(type, RESULT_MISS, len)) { |
| 332 | Dbg(dbg_ctl, "state: regex line set to result type %s: '%s'", RESULT_MISS, inv->regex_text); |
| 333 | inv->new_result = TS_CACHE_LOOKUP_MISS; |
| 334 | } else { |
| 335 | Dbg(dbg_ctl, "state: unknown regex line result type '%.*s', skipping '%s'", len, type, inv->regex_text); |
| 336 | } |
| 337 | |
| 338 | // iterate through the loaded config and try to merge |
| 339 | invalidate_t *iptr = *ilist; |
| 340 | do { |
| 341 | if (0 == strcmp(inv->regex_text, iptr->regex_text)) { |
no test coverage detected