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