source: squid-ssl/trunk/fuentes/src/DiskIO/DiskDaemon/diskd.cc @ 5495

Last change on this file since 5495 was 5495, checked in by Juanma, 2 years ago

Initial release

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