]> git.neil.brown.name Git - metad.git/blob - daemon.c
7692c496b7c3ad3af2645447ab0f913c0a9dc87a
[metad.git] / daemon.c
1
2 #include        "metad.h"
3
4 typedef struct daemon_opts
5 {
6         int min;
7         int period;
8         time_t last_start;
9 } *daemon_t;
10
11 #define c(sv) ((daemon_t)((sv)->classinfo))
12
13 static int daemon_opt(service_t sv, char *opt)
14 {
15         /* understand min= period= */
16         if (strncmp(opt, "min=", 4)==0)
17         {
18                 c(sv)->min = atoi(opt+4);
19                 return 1;
20         }
21         if (strncmp(opt, "period=", 7) == 0)
22         {
23                 char *cp = opt+7;
24                 int num = atoi(cp);
25                 if (num==0) num=1;
26                 while (isdigit(*cp)) cp++;
27                 switch(*cp) {
28                 case 0: break;
29                 case 's': break;
30                 case 'm': num *= 60; break;
31                 case 'h': num *= 3600 ; break;
32                 case 'd': num *= 24*3600 ; break;
33                 default: error("bad period specifier, %s", opt); break;
34                 }
35                 c(sv)->period = num;
36                 return 1;
37         }
38         return 0;
39 }
40
41
42 static void daemon_register(service_t sv)
43 {
44         /* nothing to do.. */
45         c(sv)->last_start = 0;
46 }
47
48 static void daemon_unregister(service_t sv)
49 {
50         /* nothing to do... */
51 }
52
53 static int daemon_prefork(service_t sv)
54 {
55         return 0;
56 }
57
58 static void daemon_check(service_t sv)
59 {
60         /* make sure min are running, and watch for next period */
61         char *env[3];
62         env[0] = "METAD_REASON=min";
63         env[1] = "METAD_ARG=";
64         env[2] = NULL;
65         while (c(sv)->min > 0 && count_procs(sv) < c(sv)->min)
66         {
67                 if (new_proc(sv, env)<=0)
68                         break;
69         }
70         if (c(sv)->period > 0 &&
71             c(sv)->last_start + c(sv)->period <= time(0))
72         {
73                 env[0] = "METAD_REASON=period";
74                 new_proc(sv, env);
75                 c(sv)->last_start = time(0); /* even if it didn't start, we tried */
76         }
77         if (c(sv)->period > 0)
78                 waituntil(c(sv)->last_start + c(sv)->period);
79 }
80
81 static void daemon_init(service_t to)
82 {
83         /* create ->classinfo with defaults */
84         daemon_t n;
85
86         n = (daemon_t)malloc(sizeof(struct daemon_opts));
87         n->min = 0;
88         n->period = 0;
89         n->last_start = 0;
90         to->classinfo = n;
91 }
92
93 static void daemon_copy(service_t from, service_t to)
94 {
95         /* copy the 'state' classinfo - last_start */
96
97         c(to)->last_start = c(from)->last_start;
98 }
99
100 static void daemon_freestate(service_t sv)
101 {
102         free(sv->classinfo);
103 }
104
105
106 static void daemon_newparent(service_t sv, proc_t p)
107 {
108         c(sv)->last_start = time(0);
109 }
110
111 static void daemon_newchild(service_t sv)
112 {
113
114 }
115
116 static void daemon_send(service_t sv)
117 {
118         /* send min, period, last_start */
119         send_byte(1); /* daemon */
120         send_int(c(sv)->min);
121         send_int(c(sv)->period);
122         send_int(c(sv)->last_start);
123 }
124
125 struct class daemon_class = {
126         .class          = "daemon",
127         .c_process_opt  = daemon_opt,
128         .register_service = daemon_register,
129         .c_check_service= daemon_check,
130         .init_state     = daemon_init,
131         .copy_state     = daemon_copy,
132         .free_state     = daemon_freestate,
133         .send_class     = daemon_send,
134         .disable_service= daemon_unregister,
135         .new_parent     = daemon_newparent,
136         .new_child      = daemon_newchild,
137         .prefork        = daemon_prefork,
138 };