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