]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskDaemon/diskd.cc
Fix diskd includes
[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 "DiskIO/DiskDaemon/diomsg.h"
37 #include "hash.h"
38
39 #if HAVE_ERRNO_H
40 #include <errno.h>
41 #endif
42 #include <sys/ipc.h>
43 #include <sys/msg.h>
44 #include <sys/shm.h>
45 #if HAVE_IOSTREAM
46 #include <iostream>
47 #endif
48
49 void
50 xassert(const char *msg, const char *file, int line)
51 {
52 fprintf(stderr,"assertion failed: %s:%d: \"%s\"\n", file, line, msg);
53
54 abort();
55 }
56
57 const int diomsg::msg_snd_rcv_sz = sizeof(diomsg) - sizeof(mtyp_t);
58 #define DEBUG(LEVEL) if ((LEVEL) <= DebugLevel)
59
60 typedef struct _file_state file_state;
61
62 struct _file_state {
63 void *key;
64 file_state *next;
65 int id;
66 int fd;
67 off_t offset;
68 };
69
70 static hash_table *hash = NULL;
71 static pid_t mypid;
72 static char *shmbuf;
73 static int DebugLevel = 0;
74
75 static int
76 do_open(diomsg * r, int len, const char *buf)
77 {
78 int fd;
79 file_state *fs;
80 /*
81 * note r->offset holds open() flags
82 */
83 fd = open(buf, r->offset, 0600);
84
85 if (fd < 0) {
86 DEBUG(1) {
87 fprintf(stderr, "%d %s: ", (int) mypid, buf);
88 perror("open");
89 }
90
91 return -errno;
92 }
93
94 fs = (file_state *)xcalloc(1, sizeof(*fs));
95 fs->id = r->id;
96 fs->key = &fs->id; /* gack */
97 fs->fd = fd;
98 hash_join(hash, (hash_link *) fs);
99 DEBUG(2) {
100 fprintf(stderr, "%d OPEN id %d, FD %d, fs %p\n",
101 (int) mypid,
102 fs->id,
103 fs->fd,
104 fs);
105 }
106 return fd;
107 }
108
109 static int
110 do_close(diomsg * r, int len)
111 {
112 int fd;
113 file_state *fs;
114 fs = (file_state *) hash_lookup(hash, &r->id);
115
116 if (NULL == fs) {
117 errno = EBADF;
118 DEBUG(1) {
119 fprintf(stderr, "%d CLOSE id %d: ", (int) mypid, r->id);
120 perror("do_close");
121 }
122
123 return -errno;
124 }
125
126 fd = fs->fd;
127 hash_remove_link(hash, (hash_link *) fs);
128 DEBUG(2) {
129 fprintf(stderr, "%d CLOSE id %d, FD %d, fs %p\n",
130 (int) mypid,
131 r->id,
132 fs->fd,
133 fs);
134 }
135 xfree(fs);
136 return close(fd);
137 }
138
139 static int
140 do_read(diomsg * r, int len, char *buf)
141 {
142 int x;
143 int readlen = r->size;
144 file_state *fs;
145 fs = (file_state *) hash_lookup(hash, &r->id);
146
147 if (NULL == fs) {
148 errno = EBADF;
149 DEBUG(1) {
150 fprintf(stderr, "%d READ id %d: ", (int) mypid, r->id);
151 perror("do_read");
152 }
153
154 return -errno;
155 }
156
157 if (r->offset > -1 && r->offset != fs->offset) {
158 DEBUG(2) {
159 fprintf(stderr, "seeking to %"PRId64"\n", (int64_t)r->offset);
160 }
161
162 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
163 DEBUG(1) {
164 fprintf(stderr, "%d FD %d, offset %"PRId64": ", (int) mypid, fs->fd, (int64_t)r->offset);
165 perror("lseek");
166 }
167 }
168 }
169
170 x = read(fs->fd, buf, readlen);
171 DEBUG(2) {
172 fprintf(stderr, "%d READ %d,%d,%"PRId64" ret %d\n", (int) mypid,
173 fs->fd, readlen, (int64_t)r->offset, x);
174 }
175
176 if (x < 0) {
177 DEBUG(1) {
178 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
179 perror("read");
180 }
181
182 return -errno;
183 }
184
185 fs->offset = r->offset + x;
186 return x;
187 }
188
189 static int
190 do_write(diomsg * r, int len, const char *buf)
191 {
192 int wrtlen = r->size;
193 int x;
194 file_state *fs;
195 fs = (file_state *) hash_lookup(hash, &r->id);
196
197 if (NULL == fs) {
198 errno = EBADF;
199 DEBUG(1) {
200 fprintf(stderr, "%d WRITE id %d: ", (int) mypid, r->id);
201 perror("do_write");
202 }
203
204 return -errno;
205 }
206
207 if (r->offset > -1 && r->offset != fs->offset) {
208 if (lseek(fs->fd, r->offset, SEEK_SET) < 0) {
209 DEBUG(1) {
210 fprintf(stderr, "%d FD %d, offset %"PRId64": ", (int) mypid, fs->fd, (int64_t)r->offset);
211 perror("lseek");
212 }
213 }
214 }
215
216 DEBUG(2) {
217 fprintf(stderr, "%d WRITE %d,%d,%"PRId64"\n", (int) mypid,
218 fs->fd, wrtlen, (int64_t)r->offset);
219 }
220 x = write(fs->fd, buf, wrtlen);
221
222 if (x < 0) {
223 DEBUG(1) {
224 fprintf(stderr, "%d FD %d: ", (int) mypid, fs->fd);
225 perror("write");
226 }
227
228 return -errno;
229 }
230
231 fs->offset = r->offset + x;
232 return x;
233 }
234
235 static int
236 do_unlink(diomsg * r, int len, const char *buf)
237 {
238 if (unlink(buf) < 0) {
239 DEBUG(1) {
240 fprintf(stderr, "%d UNLNK id %d %s: ", (int) mypid, r->id, buf);
241 perror("unlink");
242 }
243
244 return -errno;
245 }
246
247 DEBUG(2) {
248 fprintf(stderr, "%d UNLNK %s\n", (int) mypid, buf);
249 }
250 return 0;
251 }
252
253 static void
254 msg_handle(diomsg * r, int rl, diomsg * s)
255 {
256 char *buf = NULL;
257 s->mtype = r->mtype;
258 s->id = r->id;
259 s->seq_no = r->seq_no; /* optional, debugging */
260 s->callback_data = r->callback_data;
261 s->requestor = r->requestor;
262 s->size = 0; /* optional, debugging */
263 s->offset = 0; /* optional, debugging */
264 s->shm_offset = r->shm_offset;
265 s->newstyle = r->newstyle;
266
267 if (s->shm_offset > -1)
268 buf = shmbuf + s->shm_offset;
269
270 switch (r->mtype) {
271
272 case _MQD_OPEN:
273
274 case _MQD_CREATE:
275 s->status = do_open(r, rl, buf);
276 break;
277
278 case _MQD_CLOSE:
279 s->status = do_close(r, rl);
280 break;
281
282 case _MQD_READ:
283 s->status = do_read(r, rl, buf);
284 break;
285
286 case _MQD_WRITE:
287 s->status = do_write(r, rl, buf);
288 break;
289
290 case _MQD_UNLINK:
291 s->status = do_unlink(r, rl, buf);
292 break;
293
294 default:
295 assert(0);
296 break;
297 }
298 }
299
300 static int
301 fsCmp(const void *a, const void *b)
302 {
303 const int *A = (const int *)a;
304 const int *B = (const int *)b;
305 return *A != *B;
306 }
307
308 static unsigned int
309 fsHash(const void *key, unsigned int n)
310 {
311 /* note, n must be a power of 2! */
312 const int *k = (const int *)key;
313 return (*k & (--n));
314 }
315
316 SQUIDCEXTERN {
317 static void
318 alarm_handler(int sig) {
319 (void) 0;
320 }
321 };
322
323 int
324 main(int argc, char *argv[])
325 {
326 int key;
327 int rmsgid;
328 int smsgid;
329 int shmid;
330 diomsg rmsg;
331 diomsg smsg;
332 int rlen;
333 char rbuf[512];
334
335 struct sigaction sa;
336 setbuf(stdout, NULL);
337 setbuf(stderr, NULL);
338 mypid = getpid();
339 assert(4 == argc);
340 key = atoi(argv[1]);
341 rmsgid = msgget(key, 0600);
342
343 if (rmsgid < 0) {
344 perror("msgget");
345 return 1;
346 }
347
348 key = atoi(argv[2]);
349 smsgid = msgget(key, 0600);
350
351 if (smsgid < 0) {
352 perror("msgget");
353 return 1;
354 }
355
356 key = atoi(argv[3]);
357 shmid = shmget(key, 0, 0600);
358
359 if (shmid < 0) {
360 perror("shmget");
361 return 1;
362 }
363
364 shmbuf = (char *)shmat(shmid, NULL, 0);
365
366 if (shmbuf == (void *) -1) {
367 perror("shmat");
368 return 1;
369 }
370
371 hash = hash_create(fsCmp, 1 << 4, fsHash);
372 assert(hash);
373 fcntl(0, F_SETFL, SQUID_NONBLOCK);
374 memset(&sa, '\0', sizeof(sa));
375 sa.sa_handler = alarm_handler;
376 sa.sa_flags = SA_RESTART;
377 sigaction(SIGALRM, &sa, NULL);
378
379 for (;;) {
380 alarm(1);
381 memset(&rmsg, '\0', sizeof(rmsg));
382 DEBUG(2) {
383 std::cerr << "msgrcv: " << rmsgid << ", "
384 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
385 << ", " << 0 << ", " << 0 << std::endl;
386 }
387 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
388
389 if (rlen < 0) {
390 if (EINTR == errno) {
391 if (read(0, rbuf, 512) <= 0) {
392 if (EWOULDBLOCK == errno)
393 (void) 0;
394 else if (EAGAIN == errno)
395 (void) 0;
396 else
397 break;
398 }
399 }
400
401 if (EAGAIN == errno) {
402 continue;
403 }
404
405 perror("msgrcv");
406 break;
407 }
408
409 alarm(0);
410 msg_handle(&rmsg, rlen, &smsg);
411
412 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
413 perror("msgsnd");
414 break;
415 }
416 }
417
418 DEBUG(2) {
419 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
420 }
421
422 if (msgctl(rmsgid, IPC_RMID, 0) < 0)
423 perror("msgctl IPC_RMID");
424
425 if (msgctl(smsgid, IPC_RMID, 0) < 0)
426 perror("msgctl IPC_RMID");
427
428 if (shmdt(shmbuf) < 0)
429 perror("shmdt");
430
431 if (shmctl(shmid, IPC_RMID, 0) < 0)
432 perror("shmctl IPC_RMID");
433
434 return 0;
435 }