boolean_t file_checkQueueLimit(char *path, int limit) { if (limit < 0) return true; DIR *dir = opendir(path); if (! dir) { LogError("Cannot open the event queue directory %s -- %s\n", path, STRERROR); return false; } int used = 0; struct dirent *de = NULL; while ((de = readdir(dir)) ) { char buf[PATH_MAX]; snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name); if (File_isFile(buf) && ++used > limit) { LogError("Event queue is full\n"); closedir(dir); return false; } } closedir(dir); return true; }
/** * Reprocess the partially handled event queue */ void Event_queue_process() { /* return in the case that the eventqueue is not enabled or empty */ if (! Run.eventlist_dir || (! (Run.flags & Run_HandlerInit) && ! Run.handler_queue[Handler_Alert] && ! Run.handler_queue[Handler_Mmonit])) return; DIR *dir = opendir(Run.eventlist_dir); if (! dir) { if (errno != ENOENT) LogError("Cannot open the directory %s -- %s\n", Run.eventlist_dir, STRERROR); return; } struct dirent *de = readdir(dir); if (de) DEBUG("Processing postponed events queue\n"); Action_T a; NEW(a); EventAction_T ea; NEW(ea); while (de) { int handlers_passed = 0; /* In the case that all handlers failed, skip the further processing in this cycle. Alert handler is currently defined anytime (either explicitly or localhost by default) */ if ( (Run.mmonits && FLAG(Run.handler_flag, Handler_Mmonit) && FLAG(Run.handler_flag, Handler_Alert)) || FLAG(Run.handler_flag, Handler_Alert)) break; char file_name[PATH_MAX]; snprintf(file_name, sizeof(file_name), "%s/%s", Run.eventlist_dir, de->d_name); if (File_isFile(file_name)) { LogInfo("Processing queued event %s\n", file_name); FILE *file = fopen(file_name, "r"); if (! file) { LogError("Queued event processing failed - cannot open the file %s -- %s\n", file_name, STRERROR); goto error1; } size_t size; /* read event structure version */ int *version = file_readQueue(file, &size); if (! version) { LogError("skipping queued event %s - unknown data format\n", file_name); goto error2; } if (size != sizeof(int)) { LogError("Aborting queued event %s - invalid size %lu\n", file_name, (unsigned long)size); goto error3; } if (*version != EVENT_VERSION) { LogError("Aborting queued event %s - incompatible data format version %d\n", file_name, *version); goto error3; } /* read event structure */ Event_T e = file_readQueue(file, &size); if (! e) goto error3; if (size != sizeof(*e)) goto error4; /* read source */ char *service = file_readQueue(file, &size); if (! service) goto error4; if (! (e->source = Util_getService(service))) { LogError("Aborting queued event %s - service %s not found in monitor configuration\n", file_name, service); FREE(service); goto error4; } FREE(service); /* read message */ if (! (e->message = file_readQueue(file, &size))) goto error4; /* read event action */ Action_Type *action = file_readQueue(file, &size); if (! action) goto error5; if (size != sizeof(Action_Type)) goto error6; a->id = *action; switch (e->state) { case State_Succeeded: case State_ChangedNot: ea->succeeded = a; break; case State_Failed: case State_Changed: case State_Init: ea->failed = a; break; default: LogError("Aborting queue event %s -- invalid state: %d\n", file_name, e->state); goto error6; } e->action = ea; /* Retry all remaining handlers */ /* alert */ if (e->flag & Handler_Alert) { if (Run.flags & Run_HandlerInit) Run.handler_queue[Handler_Alert]++; if ((Run.handler_flag & Handler_Alert) != Handler_Alert) { if ( handle_alert(e) != Handler_Alert ) { e->flag &= ~Handler_Alert; Run.handler_queue[Handler_Alert]--; handlers_passed++; } else { LogError("Alert handler failed, retry scheduled for next cycle\n"); Run.handler_flag |= Handler_Alert; } } } /* mmonit */ if (e->flag & Handler_Mmonit) { if (Run.flags & Run_HandlerInit) Run.handler_queue[Handler_Mmonit]++; if ((Run.handler_flag & Handler_Mmonit) != Handler_Mmonit) { if ( handle_mmonit(e) != Handler_Mmonit ) { e->flag &= ~Handler_Mmonit; Run.handler_queue[Handler_Mmonit]--; handlers_passed++; } else { LogError("M/Monit handler failed, retry scheduled for next cycle\n"); Run.handler_flag |= Handler_Mmonit; } } } /* If no error persists, remove it from the queue */ if (e->flag == Handler_Succeeded) { DEBUG("Removing queued event %s\n", file_name); if (unlink(file_name) < 0) LogError("Failed to remove queued event file '%s' -- %s\n", file_name, STRERROR); } else if (handlers_passed > 0) { DEBUG("Updating queued event %s (some handlers passed)\n", file_name); _queueUpdate(e, file_name); } error6: FREE(action); error5: FREE(e->message); error4: FREE(e); error3: FREE(version); error2: fclose(file); } error1: de = readdir(dir); } Run.flags &= ~Run_HandlerInit; closedir(dir); FREE(a); FREE(ea); }