source: trunk/third/linc/src/cleanup.c @ 18242

Revision 18242, 4.0 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18241, which included commits to RCS files with non-trunk default branches.
Line 
1#include <config.h>
2
3#include <stdio.h>
4#include <fcntl.h>
5#include <unistd.h>
6#include <dirent.h>
7#include <glib.h>
8
9/*
10 * Two timeouts - waiting while there are other
11 *  ( in ms )     handles to be checked.
12 *              - waiting after all other handles have
13 *                been checked.
14 */
15#define SHORT_TIMEOUT  10
16#define LONG_TIMEOUT 1000
17
18static int total_count = 0;
19static int cleaned_count = 0;
20
21#include <linc-compat.h>
22
23#ifdef AF_UNIX
24
25typedef struct {
26        char *name;
27        int   fd;
28} SocketEntry;
29
30static SocketEntry *
31new_socket_entry (const char *dir, const char *fname)
32{
33        SocketEntry *se = g_new0 (SocketEntry, 1);
34
35        se->name = g_build_filename (dir, fname, NULL);
36        se->fd = -1;
37
38        return se;
39}
40
41static void
42free_socket_entry (SocketEntry *se)
43{
44        g_free (se->name);
45        if (se->fd >= 0)
46                close (se->fd);
47        g_free (se);
48}
49
50static GList *
51read_sockets (const char *dir)
52{
53        DIR   *dirh;
54        GList *files = NULL;
55        struct dirent *dent;
56
57        dirh = opendir (dir);
58
59        while ((dent = readdir (dirh))) {
60                if (strncmp (dent->d_name, "linc-", 5))
61                        continue;
62
63                files = g_list_prepend (
64                        files, new_socket_entry (
65                                dir, dent->d_name));
66        }
67        closedir (dirh);
68
69        return files;
70}
71
72typedef enum {
73        SOCKET_DEAD_NOW,
74        SOCKET_PENDING,
75        SOCKET_AGAIN,
76        SOCKET_ALIVE
77} SocketStatus;
78
79static SocketStatus
80open_socket (SocketEntry *se)
81{
82        int saddr_len, ret;
83        struct sockaddr_un saddr;
84
85        g_return_val_if_fail (se != NULL, SOCKET_DEAD_NOW);
86        g_return_val_if_fail (se->fd == -1, SOCKET_DEAD_NOW);
87        g_return_val_if_fail (se->name != NULL, SOCKET_DEAD_NOW);
88
89        saddr.sun_family = AF_UNIX;
90
91        g_snprintf (saddr.sun_path, sizeof (saddr.sun_path),
92                    "%s", se->name);
93
94        se->fd = socket (AF_UNIX, SOCK_STREAM, 0);
95        g_assert (se->fd >= 0);
96
97        if (fcntl (se->fd, F_SETFL, O_NONBLOCK) < 0)
98                g_error ("Failed to set fd non-blocking");
99       
100        saddr_len = sizeof (struct sockaddr_un) -
101                sizeof (saddr.sun_path) + strlen (saddr.sun_path);
102
103        do {
104                ret = connect (se->fd, &saddr, saddr_len);
105        } while (ret < 0 && errno == EINTR);
106
107        if (ret >= 0)
108                return SOCKET_ALIVE;
109        else {
110                switch (errno) {
111                case EINPROGRESS:
112                        return SOCKET_PENDING;
113                case ECONNREFUSED:
114                        return SOCKET_DEAD_NOW;
115                case EAGAIN:
116                        return SOCKET_AGAIN;
117                case EBADF:
118                        g_error ("Bad bug fd %d", se->fd);
119                        break;
120                default:
121                        g_warning ("Error '%s' on socket %d",
122                                   g_strerror (errno), se->fd);
123                        break;
124                }
125        }
126
127        return SOCKET_DEAD_NOW;
128}
129
130static GList *
131poll_open (GList *files, int *pending, int timeout)
132{
133        if (!files)
134                return NULL;
135
136        g_print ("FIXME: should poll unknown descriptors for a bit");
137
138        /* FIXME: we should really do something clever here,
139         * poll for a while, wait for nice connected / bad
140         * signals on the sockets, etc - but what we have
141         * works well for now */
142        while (files && *pending > 0) {
143                free_socket_entry (files->data);
144                files = g_list_delete_link (files, files);
145                (*pending)--;
146        }
147
148        return files;
149}
150
151static void
152clean_dir (const char *dir)
153{
154        int open_max;
155        int pending = 0;
156        int dirty_files = 0;
157        GList *files, *l, *next;
158
159        open_max = sysconf (_SC_OPEN_MAX);
160
161        files = read_sockets (dir);
162
163        dirty_files = g_list_length (files);
164
165        for (l = files; l; l = next) {
166                SocketEntry *se = l->data;
167                SocketStatus status;
168
169                next = l->next;
170               
171                status = open_socket (se);
172
173                switch (status) {
174                case SOCKET_DEAD_NOW:
175                        cleaned_count++;
176                        unlink (se->name);
177                        /* drop through */
178                case SOCKET_ALIVE:
179                        files = g_list_delete_link (files, l);
180                        free_socket_entry (se);
181                        total_count++;
182                        break;
183                case SOCKET_AGAIN:
184                case SOCKET_PENDING:
185                        pending++;
186                        break;
187                }
188
189                while (pending >= open_max)
190                        files = poll_open (
191                                files, &pending, SHORT_TIMEOUT);
192        }
193
194        files = poll_open (files, &pending, LONG_TIMEOUT);
195
196        while (files) {
197                free_socket_entry (files->data);
198                files = g_list_delete_link (files, files);
199        }
200}
201
202#endif /* AF_UNIX */
203
204int
205main (int argc, char **argv)
206{
207        char *dir;
208
209        dir = g_strdup_printf ("/tmp/orbit-%s", g_get_user_name ());
210
211#ifdef AF_UNIX
212        clean_dir (dir);
213#endif /* AF_UNIX */
214
215        g_free (dir);
216
217        printf ("Cleaned %d files %d still live\n",
218                cleaned_count,
219                total_count - cleaned_count);
220
221        return 0;
222}
Note: See TracBrowser for help on using the repository browser.