Use CRITICAL job priority class for long running dispatcher jobs
[strongswan.git] / src / libcharon / plugins / ha / ha_ctl.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "ha_ctl.h"
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/select.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <errno.h>
24
25 #include <threading/thread.h>
26 #include <processing/jobs/callback_job.h>
27
28 #define HA_FIFO IPSEC_PIDDIR "/charon.ha"
29
30 typedef struct private_ha_ctl_t private_ha_ctl_t;
31
32 /**
33 * Private data of an ha_ctl_t object.
34 */
35 struct private_ha_ctl_t {
36
37 /**
38 * Public ha_ctl_t interface.
39 */
40 ha_ctl_t public;
41
42 /**
43 * Segments to control
44 */
45 ha_segments_t *segments;
46
47 /**
48 * Resynchronization message cache
49 */
50 ha_cache_t *cache;
51
52 /**
53 * FIFO reader thread
54 */
55 callback_job_t *job;
56 };
57
58 /**
59 * FIFO dispatching function
60 */
61 static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
62 {
63 int fifo;
64 bool oldstate;
65 char buf[8];
66 u_int segment;
67
68 oldstate = thread_cancelability(TRUE);
69 fifo = open(HA_FIFO, O_RDONLY);
70 thread_cancelability(oldstate);
71 if (fifo == -1)
72 {
73 DBG1(DBG_CFG, "opening HA fifo failed: %s", strerror(errno));
74 sleep(1);
75 return JOB_REQUEUE_FAIR;
76 }
77
78 memset(buf, 0, sizeof(buf));
79 if (read(fifo, buf, sizeof(buf)-1) > 1)
80 {
81 segment = atoi(&buf[1]);
82 if (segment)
83 {
84 switch (buf[0])
85 {
86 case '+':
87 this->segments->activate(this->segments, segment, TRUE);
88 break;
89 case '-':
90 this->segments->deactivate(this->segments, segment, TRUE);
91 break;
92 case '*':
93 this->cache->resync(this->cache, segment);
94 break;
95 default:
96 break;
97 }
98 }
99 }
100 close(fifo);
101
102 return JOB_REQUEUE_DIRECT;
103 }
104
105 METHOD(ha_ctl_t, destroy, void,
106 private_ha_ctl_t *this)
107 {
108 this->job->cancel(this->job);
109 free(this);
110 }
111
112 /**
113 * See header
114 */
115 ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
116 {
117 private_ha_ctl_t *this;
118 mode_t old;
119
120 INIT(this,
121 .public = {
122 .destroy = _destroy,
123 },
124 .segments = segments,
125 .cache = cache,
126 );
127
128 if (access(HA_FIFO, R_OK|W_OK) != 0)
129 {
130 old = umask(~(S_IRWXU | S_IRWXG));
131 if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0)
132 {
133 DBG1(DBG_CFG, "creating HA FIFO %s failed: %s",
134 HA_FIFO, strerror(errno));
135 }
136 umask(old);
137 }
138 if (chown(HA_FIFO, charon->uid, charon->gid) != 0)
139 {
140 DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s",
141 strerror(errno));
142 }
143
144 this->job = callback_job_create_with_prio((callback_job_cb_t)dispatch_fifo,
145 this, NULL, NULL, JOB_PRIO_CRITICAL);
146 lib->processor->queue_job(lib->processor, (job_t*)this->job);
147 return &this->public;
148 }
149