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