]> git.itanic.dy.fi Git - rrdd/blobdiff - main.c
onewire_parser.c: Fix compiler warnings about string lengths
[rrdd] / main.c
diff --git a/main.c b/main.c
index fae47eddbe23c24da5d3cf4e3132ffbe01c8a5e5..d57fb0b646b36983d67da88a08cc2068435c5a78 100644 (file)
--- a/main.c
+++ b/main.c
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <unistd.h>
+#include <getopt.h>
+#include <time.h>
 
+#include "version.h"
 #include "process.h"
-#include "draw_graphs.h"
+#include "rrdtool.h"
 #include "parser.h"
-#include "scheduler.h"
 #include "debug.h"
 
-#include "testdata.h"
+#include "config.h"
+#include "built_in_parsers.h"
 
+#include "plugin_manager.h"
+
+struct user_options {
+       int max_jobs;
+       int daemonize;
+       char *config_file;
+       char *pid_file;
+};
+
+int read_args(int argc, char *argv[], struct user_options *opts)
+{
+       int option_index = 0, c;
+       static struct option long_options[] = {
+               { .val = 'j', .has_arg = 1, .name = "jobs", },
+               { .val = 'c', .has_arg = 1, .name = "config", },
+               { .val = 'l', .has_arg = 1, .name = "log-file", },
+               { .val = 'p', .has_arg = 1, .name = "pid-file", },
+               { .val = 'd', .name = "daemon", },
+               { .val = 'v', .name = "verbose", },
+               { .val = 'q', .name = "quiet", },
+               { },
+       };
+       char short_options[] = "j:c:l:p:dvq";
+
+       while (1) {
+               c = getopt_long(argc, argv, short_options, long_options,
+                               &option_index);
+
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 'j':
+                       opts->max_jobs = atoi(optarg);
+                       break;
+
+               case 'c':
+                       opts->config_file = optarg;
+                       break;
+
+               case 'l':
+                       open_log_file(optarg);
+                       break;
+
+               case 'v':
+                       trace_level++;
+                       break;
+
+               case 'q':
+                       trace_level--;
+                       break;
+
+               case 'd':
+                       opts->daemonize = 1;
+                       break;
+
+               case 'p':
+                       opts->pid_file = optarg;
+                       break;
+
+               case '?':
+                       return -1;
+               }
+       }
+
+       while (optind < argc) {
+               opts->config_file = argv[optind];
+               optind++;
+       }
+
+       return 0;
+}
+
+static int is_already_running(const char *pidfile)
+{
+       struct stat s;
+       char pidstr[16], procpath[256] = { 0 };
+       int fd, ret, pid;
+
+       fd = open(pidfile, O_RDONLY);
+       if (fd < 0) {
+               /* No pid, no running instance */
+               return 0;
+       }
+
+       ret = read(fd, pidstr, sizeof(pidstr) - 1);
+       if (ret < 0) {
+               pr_err("Failed to read pid file: %m\n");
+               close(fd);
+
+               return ret;
+       }
+       close(fd);
+
+       pidstr[ret] = 0;
+
+       ret = sscanf(pidstr, "%d", &pid);
+
+       /* Corrupted pid data? Maybe leftover from prev boot or something */
+       if (ret != 1)
+               return 0;
+
+       snprintf(procpath, sizeof(procpath) - 1, "/proc/%d/", pid);
+
+       ret = stat(procpath, &s);
+
+       if (ret < 0) {
+               pr_info("Ignoring stale pid %d from pid file %s\n",
+                       pid, pidfile);
+
+               return 0;
+       }
+
+       pr_err("Process %d is already running as stated in pid file %s\n",
+               pid, pidfile);
+
+       return 1;
+}
+
+static int write_pidfile(const char *pidfile)
+{
+       char pidstr[16];
+       int fd, ret;
+
+       fd = open(pidfile, O_WRONLY | O_CREAT, 0644);
+       if (fd < 0) {
+               pr_err("Failed to open pidfile %s for writing: %m\n", pidfile);
+               return -1;
+       }
+
+       ret = snprintf(pidstr, sizeof(pidstr), "%d", getpid());
+       ret = write(fd, pidstr, ret);
+       if (ret < 0)
+               pr_err("Failed to write to pidfile %s: %m\n", pidfile);
+
+       close(fd);
+
+       return ret;
+}
 
 int main(int argc, char *argv[])
 {
-       struct rrd_database *db;
+       struct user_options opts;
+       struct rrd_database *db, **db_list = NULL;
        int sleeptime;
+       int ret = 0;
+
+       pr_info("%s Version %s starting\n", argv[0], RRDD_VERSION);
+
+       bzero(&opts, sizeof(opts));
+
+       if (read_args(argc, argv, &opts) < 0)
+               return -1;
+
+       if (opts.daemonize) {
+               pr_info("Setting itself as a daemon\n");
+               ret = daemon(1, 0);
+               if (ret < 0) {
+                       pr_err("Failed to daemonize: %m\n");
+                       return -1;
+               }
+       }
+
+       if (opts.pid_file) {
+               if (is_already_running(opts.pid_file))
+                       return -1;
+
+               if (write_pidfile(opts.pid_file) < 0)
+                       return -1;
+       }
+
+       init_plugin_manager(argv[0]);
+       register_built_in_parsers();
+       register_network_parser();
+
+       if (!opts.config_file) {
+               pr_err("No database config file given. Nothing to do\n");
+               return 1;
+       }
+
+       db_list = populate_database(opts.config_file);
+
+       if (ret || !db_list)
+               return 1;
+
+       if (rrdtool_create_missing_databases(db_list))
+               return 1;
+
+       if (init_jobcontrol(opts.max_jobs))
+               return -1;
 
        while (1) {
-               pr_info("loop start\n");
+               const char *db_name;
+               char timestr[128];
+               time_t t;
+
                /*
                 * Update all databases parallel in one shot
                 */
-               while ((db = check_update_need((struct rrd_database **)
-                                              &all_rrds)))
-                       update_data(db);
+               while ((db = get_outdated_db(db_list)))
+                       rrdtool_update_data(db);
 
-               /*
-                * Let the updates finish
-                */
-               if (harvest_zombies(0))
-                       continue;
+               sleeptime = get_next_update(db_list, &db_name);
 
-               sleeptime = get_next_update((struct rrd_database **)&all_rrds);
-               pr_info("Time to sleep %d seconds\n", sleeptime);
-               sleep(sleeptime);
+               if (sleeptime >=  0) {
+                       t = time(0) + sleeptime;
+                       strftime(timestr, sizeof(timestr), "%T", localtime(&t));
+                       pr_info("Next scheduled event \"%s\" at %s, in %d seconds\n",
+                               db_name, timestr, sleeptime);
+               } else
+                       pr_info("All jobs active, sleeping until event arrives\n");
 
+               poll_job_requests(sleeptime);
        }
        return 0;
 }