]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskDaemon/diskd.cc
Merged from parent (trunk r11240, circa 3.2.0.5+)
[thirdparty/squid.git] / src / DiskIO / DiskDaemon / diskd.cc
1 /*
2 * $Id$
3 *
4 * DEBUG: section -- External DISKD process implementation.
5 * AUTHOR: Harvest Derived
6 *
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34
35 #include "config.h"
36 #include "squid.h"
37
38 #include <sys/ipc.h>
39 #include <sys/msg.h>
40 #include <sys/shm.h>
41
42 #include "DiskIO/DiskDaemon/diomsg.h"
43
44 void
45 xassert(const char *msg, const char *file, int line)
46 {
47 fprintf(stderr,"assertion failed: %s:%d: \"%s\"\n", file, line, msg);
48
49 abort();
50 }
51
52 const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
53 #define DEBUG(LEVEL) if ((LEVEL) <= DebugLevel)
54
55 typedef struct _file_state file_state;
56
57 struct _file_state {
58 void *key;
59 file_state *next;
60 int id;
61 int fd;
62 off_t offset;
63 };
64
65 static hash_table *hash = NULL;
66 static pid_t mypid;
67 static char *shmbuf;
68 static int DebugLevel = 0;
69
70 static int
71 do_open(diomsg * r, int len, const char *buf)
72 {
73 int fd;
74 file_state *fs;
75 /*
76 * note r->offset holds open() flags
77 */
78 fd = open(buf, r->offset, 0600);
79
80 if (fd < 0) {
81 DEBUG(1) {
82 fprintf(stderr, "%d %s: ", (int) mypid, buf);
83 perror("open");
84 }
85
86 return -errno;
87 }
88
89 fs = (file_state *)xcalloc(1, sizeof(*fs));
90 fs->id = r->id;
91 fs->key = &fs->id; /* gack */
92 fs->fd = fd;
93 hash_join(hash, (hash_link *) fs);
94 DEBUG(2) {
95 fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
96 (int) mypid,
97 fs->id,
98 fs->fd,
99 fs);
100 }
101 return fd;
102 }
103
104 static int
105 do_close(diomsg * r, int len)
106 {
107 int fd;
108 file_state *fs;
109 fs = (file_state *) hash_lookup(hash, &r->id);
110
111 if (NULL == fs) {
112 errno = EBADF;
113 DEBUG(1) {
114 fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id);
115 perror("do_close");
116 }
117
118 return -errno;
119 }
120
121 fd = fs->fd;
122 hash_remove_link(hash, (hash_link *) fs);
123 DEBUG(2) {
124 fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
125 (int) mypid,
126 r->id,
127 fs->fd,
128 fs);
129 }
130 xfree(fs);
131 return close(fd);
132 }
133
134 static int
135 do_read(diomsg * r, int len, char *buf)
136 {
137 int x;
138 int readlen = r->size;
139 file_state *fs;
140 fs = (file_state *) hash_lookup(hash, &r->id);
141
142 if (NULL == fs) {
143 errno = EBADF;
144 DEBUG(1) {
145 fprintf(stderr, "%d READ id %d: ", (int) mypid, r->id);
146 perror("do_read");
147 }
148
149 return -errno;
150 }
151
152 if (r->offset > -1 && r->offset != fs->offset) {
153 DEBUG(2) {
154 fprintf(stderr, "seeking to %"PRId64"\n", (int64_t)r->offset);
155 }
156
157 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
158 DEBUG(1) {
159 fprintf(stderr, "%d FD %d, offset %"PRId64": ", (int) mypid, fs->fd, (int64_t)r->offset);
160 perror("lseek");
161 }
162 }
163 }
164
165 x = read(fs->fd, buf, readlen);
166 DEBUG(2) {
167 fprintf(stderr, "%d READ %d,%d,%"PRId64" ret %d\n", (int) mypid,
168 fs->fd, readlen, (int64_t)r->offset, x);
169 }
170
171 if (x < 0) {
172 DEBUG(1) {
173 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
174 perror("read");
175 }
176
177 return -errno;
178 }
179
180 fs->offset = r->offset + x;
181 return x;
182 }
183
184 static int
185 do_write(diomsg * r, int len, const char *buf)
186 {
187 int wrtlen = r->size;
188 int x;
189 file_state *fs;
190 fs = (file_state *) hash_lookup(hash, &r->id);
191
192 if (NULL == fs) {
193 errno = EBADF;
194 DEBUG(1) {
195 fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id);
196 perror("do_write");
197 }
198
199 return -errno;
200 }
201
202 if (r->offset > -1 && r->offset != fs->offset) {
203 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
204 DEBUG(1) {
205 fprintf(stderr, "%d FD %d, offset %"PRId64": ", (int) mypid, fs->fd, (int64_t)r->offset);
206 perror("lseek");
207 }
208 }
209 }
210
211 DEBUG(2) {
212 fprintf(stderr, "%d WRITE %d,%d,%"PRId64"\n", (int) mypid,
213 fs->fd, wrtlen, (int64_t)r->offset);
214 }
215 x = write(fs->fd, buf, wrtlen);
216
217 if (x < 0) {
218 DEBUG(1) {
219 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
220 perror("write");
221 }
222
223 return -errno;
224 }
225
226 fs->offset = r->offset + x;
227 return x;
228 }
229
230 static int
231 do_unlink(diomsg * r, int len, const char *buf)
232 {
233 if (unlink(buf) < 0) {
234 DEBUG(1) {
235 fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf);
236 perror("unlink");
237 }
238
239 return -errno;
240 }
241
242 DEBUG(2) {
243 fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
244 }
245 return 0;
246 }
247
248 static void
249 msg_handle(diomsg * r, int rl, diomsg * s)
250 {
251 char *buf = NULL;
252 s->mtype = r->mtype;
253 s->id = r->id;
254 s->seq_no = r->seq_no; /* optional, debugging */
255 s->callback_data = r->callback_data;
256 s->requestor = r->requestor;
257 s->size = 0; /* optional, debugging */
258 s->offset = 0; /* optional, debugging */
259 s->shm_offset = r->shm_offset;
260 s->newstyle = r->newstyle;
261
262 if (s->shm_offset > -1)
263 buf = shmbuf + s->shm_offset;
264
265 switch (r->mtype) {
266
267 case _MQD_OPEN:
268
269 case _MQD_CREATE:
270 s->status = do_open(r, rl, buf);
271 break;
272
273 case _MQD_CLOSE:
274 s->status = do_close(r, rl);
275 break;
276
277 case _MQD_READ:
278 s->status = do_read(r, rl, buf);
279 break;
280
281 case _MQD_WRITE:
282 s->status = do_write(r, rl, buf);
283 break;
284
285 case _MQD_UNLINK:
286 s->status = do_unlink(r, rl, buf);
287 break;
288
289 default:
290 assert(0);
291 break;
292 }
293 }
294
295 static int
296 fsCmp(const void *a, const void *b)
297 {
298 const int *A = (const int *)a;
299 const int *B = (const int *)b;
300 return *A != *B;
301 }
302
303 static unsigned int
304 fsHash(const void *key, unsigned int n)
305 {
306 /* note, n must be a power of 2! */
307 const int *k = (const int *)key;
308 return (*k & (--n));
309 }
310
311 SQUIDCEXTERN {
312 static void
313 alarm_handler(int sig) {
314 (void) 0;
315 }
316 };
317
318 int
319 main(int argc, char *argv[])
320 {
321 int key;
322 int rmsgid;
323 int smsgid;
324 int shmid;
325 diomsg rmsg;
326 diomsg smsg;
327 int rlen;
328 char rbuf[512];
329
330 struct sigaction sa;
331 setbuf(stdout, NULL);
332 setbuf(stderr, NULL);
333 mypid = getpid();
334 assert(4 == argc);
335 key = atoi(argv[1]);
336 rmsgid = msgget(key, 0600);
337
338 if (rmsgid < 0) {
339 perror("msgget");
340 return 1;
341 }
342
343 key = atoi(argv[2]);
344 smsgid = msgget(key, 0600);
345
346 if (smsgid < 0) {
347 perror("msgget");
348 return 1;
349 }
350
351 key = atoi(argv[3]);
352 shmid = shmget(key, 0, 0600);
353
354 if (shmid < 0) {
355 perror("shmget");
356 return 1;
357 }
358
359 shmbuf = (char *)shmat(shmid, NULL, 0);
360
361 if (shmbuf == (void *) -1) {
362 perror("shmat");
363 return 1;
364 }
365
366 hash = hash_create(fsCmp, 1 << 4, fsHash);
367 assert(hash);
368 fcntl(0, F_SETFL, SQUID_NONBLOCK);
369 memset(&sa, '\0', sizeof(sa));
370 sa.sa_handler = alarm_handler;
371 sa.sa_flags = SA_RESTART;
372 sigaction(SIGALRM, &sa, NULL);
373
374 for (;;) {
375 alarm(1);
376 memset(&rmsg, '\0', sizeof(rmsg));
377 DEBUG(2) {
378 std::cerr << "msgrcv: " << rmsgid << ", "
379 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
380 << ", " << 0 << ", " << 0 << std::endl;
381 }
382 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
383
384 if (rlen < 0) {
385 if (EINTR == errno) {
386 if (read(0, rbuf, 512) <= 0) {
387 if (EWOULDBLOCK == errno)
388 (void) 0;
389 else if (EAGAIN == errno)
390 (void) 0;
391 else
392 break;
393 }
394 }
395
396 if (EAGAIN == errno) {
397 continue;
398 }
399
400 perror("msgrcv");
401 break;
402 }
403
404 alarm(0);
405 msg_handle(&rmsg, rlen, &smsg);
406
407 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
408 perror("msgsnd");
409 break;
410 }
411 }
412
413 DEBUG(2) {
414 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
415 }
416
417 if (msgctl(rmsgid, IPC_RMID, 0) < 0)
418 perror("msgctl IPC_RMID");
419
420 if (msgctl(smsgid, IPC_RMID, 0) < 0)
421 perror("msgctl IPC_RMID");
422
423 if (shmdt(shmbuf) < 0)
424 perror("shmdt");
425
426 if (shmctl(shmid, IPC_RMID, 0) < 0)
427 perror("shmctl IPC_RMID");
428
429 return 0;
430 }