]> git.ipfire.org Git - thirdparty/squid.git/blob - src/DiskIO/DiskDaemon/diskd.cc
Cleanup: un-wrap C++ header includes
[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 #include <cerrno>
38 #include <iostream>
39 #if HAVE_SYS_IPC_H
40 #include <sys/ipc.h>
41 #endif
42 #if HAVE_SYS_MSG_H
43 #include <sys/msg.h>
44 #endif
45 #if HAVE_SYS_SHM_H
46 #include <sys/shm.h>
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 else if (r->mtype != _MQD_CLOSE) {
270 fprintf(stderr, "%d UNLNK id(%u) Error: no filename in shm buffer\n", (int) mypid, s->id);
271 return;
272 }
273
274 switch (r->mtype) {
275
276 case _MQD_OPEN:
277
278 case _MQD_CREATE:
279 s->status = do_open(r, rl, buf);
280 break;
281
282 case _MQD_CLOSE:
283 s->status = do_close(r, rl);
284 break;
285
286 case _MQD_READ:
287 s->status = do_read(r, rl, buf);
288 break;
289
290 case _MQD_WRITE:
291 s->status = do_write(r, rl, buf);
292 break;
293
294 case _MQD_UNLINK:
295 s->status = do_unlink(r, rl, buf);
296 break;
297
298 default:
299 assert(0);
300 break;
301 }
302 }
303
304 static int
305 fsCmp(const void *a, const void *b)
306 {
307 const int *A = (const int *)a;
308 const int *B = (const int *)b;
309 return *A != *B;
310 }
311
312 static unsigned int
313 fsHash(const void *key, unsigned int n)
314 {
315 /* note, n must be a power of 2! */
316 const int *k = (const int *)key;
317 return (*k & (--n));
318 }
319
320 SQUIDCEXTERN {
321 static void
322 alarm_handler(int sig) {
323 (void) 0;
324 }
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 if (fcntl(0, F_SETFL, SQUID_NONBLOCK) < 0) {
378 perror(xstrerror());
379 return 1;
380 }
381 memset(&sa, '\0', sizeof(sa));
382 sa.sa_handler = alarm_handler;
383 sa.sa_flags = SA_RESTART;
384 sigaction(SIGALRM, &sa, NULL);
385
386 for (;;) {
387 alarm(1);
388 memset(&rmsg, '\0', sizeof(rmsg));
389 DEBUG(2) {
390 std::cerr << "msgrcv: " << rmsgid << ", "
391 << &rmsg << ", " << diomsg::msg_snd_rcv_sz
392 << ", " << 0 << ", " << 0 << std::endl;
393 }
394 rlen = msgrcv(rmsgid, &rmsg, diomsg::msg_snd_rcv_sz, 0, 0);
395
396 if (rlen < 0) {
397 if (EINTR == errno) {
398 if (read(0, rbuf, 512) <= 0) {
399 if (EWOULDBLOCK == errno)
400 (void) 0;
401 else if (EAGAIN == errno)
402 (void) 0;
403 else
404 break;
405 }
406 }
407
408 if (EAGAIN == errno) {
409 continue;
410 }
411
412 perror("msgrcv");
413 break;
414 }
415
416 alarm(0);
417 msg_handle(&rmsg, rlen, &smsg);
418
419 if (msgsnd(smsgid, &smsg, diomsg::msg_snd_rcv_sz, 0) < 0) {
420 perror("msgsnd");
421 break;
422 }
423 }
424
425 DEBUG(2) {
426 fprintf(stderr, "%d diskd exiting\n", (int) mypid);
427 }
428
429 if (msgctl(rmsgid, IPC_RMID, 0) < 0)
430 perror("msgctl IPC_RMID");
431
432 if (msgctl(smsgid, IPC_RMID, 0) < 0)
433 perror("msgctl IPC_RMID");
434
435 if (shmdt(shmbuf) < 0)
436 perror("shmdt");
437
438 if (shmctl(shmid, IPC_RMID, 0) < 0)
439 perror("shmctl IPC_RMID");
440
441 return 0;
442 }