]> git.ipfire.org Git - thirdparty/squid.git/blob - src/fd.cc
Removed squid-old.h
[thirdparty/squid.git] / src / fd.cc
1
2 /*
3 * $Id$
4 *
5 * DEBUG: section 51 Filedescriptor Functions
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36 #include "squid.h"
37 #include "comm/Loops.h"
38 #include "Debug.h"
39 #include "fde.h"
40 #include "globals.h"
41 #include "profiler/Profiler.h"
42 #include "SquidTime.h"
43
44
45 // Solaris and possibly others lack MSG_NOSIGNAL optimization
46 // TODO: move this into compat/? Use a dedicated compat file to avoid dragging
47 // sys/types.h and sys/socket.h into the rest of Squid??
48 #ifndef MSG_NOSIGNAL
49 #define MSG_NOSIGNAL 0
50 #endif
51
52 int default_read_method(int, char *, int);
53 int default_write_method(int, const char *, int);
54 #if _SQUID_MSWIN_
55 int socket_read_method(int, char *, int);
56 int socket_write_method(int, const char *, int);
57 int file_read_method(int, char *, int);
58 int file_write_method(int, const char *, int);
59 #else
60 int msghdr_read_method(int, char *, int);
61 int msghdr_write_method(int, const char *, int);
62 #endif
63
64 const char *fdTypeStr[] = {
65 "None",
66 "Log",
67 "File",
68 "Socket",
69 "Pipe",
70 "MsgHdr",
71 "Unknown"
72 };
73
74 static void fdUpdateBiggest(int fd, int);
75
76 static void
77 fdUpdateBiggest(int fd, int opening)
78 {
79 if (fd < Biggest_FD)
80 return;
81
82 assert(fd < Squid_MaxFD);
83
84 if (fd > Biggest_FD) {
85 /*
86 * assert that we are not closing a FD bigger than
87 * our known biggest FD
88 */
89 assert(opening);
90 Biggest_FD = fd;
91 return;
92 }
93
94 /* if we are here, then fd == Biggest_FD */
95 /*
96 * assert that we are closing the biggest FD; we can't be
97 * re-opening it
98 */
99 assert(!opening);
100
101 while (Biggest_FD >= 0 && !fd_table[Biggest_FD].flags.open)
102 --Biggest_FD;
103 }
104
105 void
106 fd_close(int fd)
107 {
108 fde *F = &fd_table[fd];
109
110 assert(fd >= 0);
111 assert(F->flags.open == 1);
112
113 if (F->type == FD_FILE) {
114 assert(F->read_handler == NULL);
115 assert(F->write_handler == NULL);
116 }
117
118 debugs(51, 3, "fd_close FD " << fd << " " << F->desc);
119 Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
120 Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
121 F->flags.open = 0;
122 fdUpdateBiggest(fd, 0);
123 --Number_FD;
124 *F = fde();
125 }
126
127 #if _SQUID_MSWIN_
128
129 int
130 socket_read_method(int fd, char *buf, int len)
131 {
132 int i;
133 PROF_start(recv);
134 i = recv(fd, (void *) buf, len, 0);
135 PROF_stop(recv);
136 return i;
137 }
138
139 int
140 file_read_method(int fd, char *buf, int len)
141 {
142 int i;
143 PROF_start(read);
144 i = _read(fd, buf, len);
145 PROF_stop(read);
146 return i;
147 }
148
149 int
150 socket_write_method(int fd, const char *buf, int len)
151 {
152 int i;
153 PROF_start(send);
154 i = send(fd, (const void *) buf, len, 0);
155 PROF_stop(send);
156 return i;
157 }
158
159 int
160 file_write_method(int fd, const char *buf, int len)
161 {
162 int i;
163 PROF_start(write);
164 i = (_write(fd, buf, len));
165 PROF_stop(write);
166 return i;
167 }
168
169 #else
170 int
171 default_read_method(int fd, char *buf, int len)
172 {
173 int i;
174 PROF_start(read);
175 i = read(fd, buf, len);
176 PROF_stop(read);
177 return i;
178 }
179
180 int
181 default_write_method(int fd, const char *buf, int len)
182 {
183 int i;
184 PROF_start(write);
185 i = write(fd, buf, len);
186 PROF_stop(write);
187 return i;
188 }
189
190 int
191 msghdr_read_method(int fd, char *buf, int len)
192 {
193 PROF_start(read);
194 const int i = recvmsg(fd, reinterpret_cast<msghdr*>(buf), MSG_DONTWAIT);
195 PROF_stop(read);
196 return i;
197 }
198
199 int
200 msghdr_write_method(int fd, const char *buf, int len)
201 {
202 PROF_start(write);
203 const int i = sendmsg(fd, reinterpret_cast<const msghdr*>(buf), MSG_NOSIGNAL);
204 PROF_stop(write);
205 return i > 0 ? len : i; // len is imprecise but the caller expects a match
206 }
207
208 #endif
209
210 void
211 fd_open(int fd, unsigned int type, const char *desc)
212 {
213 fde *F;
214 assert(fd >= 0);
215 F = &fd_table[fd];
216
217 if (F->flags.open) {
218 debugs(51, DBG_IMPORTANT, "WARNING: Closing open FD " << std::setw(4) << fd);
219 fd_close(fd);
220 }
221
222 assert(!F->flags.open);
223 debugs(51, 3, "fd_open() FD " << fd << " " << desc);
224 F->type = type;
225 F->flags.open = 1;
226 F->epoll_state = 0;
227 #if _SQUID_MSWIN_
228
229 F->win32.handle = _get_osfhandle(fd);
230
231 switch (type) {
232
233 case FD_SOCKET:
234
235 case FD_PIPE:
236 F->read_method = &socket_read_method;
237 F->write_method = &socket_write_method;
238 break;
239
240 case FD_FILE:
241
242 case FD_LOG:
243 F->read_method = &file_read_method;
244 F->write_method = &file_write_method;
245 break;
246
247 default:
248 fatalf("fd_open(): unknown FD type - FD#: %i, type: %u, desc %s\n", fd, type, desc);
249 }
250
251 #else
252 switch (type) {
253
254 case FD_MSGHDR:
255 F->read_method = &msghdr_read_method;
256 F->write_method = &msghdr_write_method;
257 break;
258
259 default:
260 F->read_method = &default_read_method;
261 F->write_method = &default_write_method;
262 break;
263 }
264
265 #endif
266
267 fdUpdateBiggest(fd, 1);
268
269 if (desc)
270 xstrncpy(F->desc, desc, FD_DESC_SZ);
271
272 ++Number_FD;
273 }
274
275 void
276 fd_note(int fd, const char *s)
277 {
278 fde *F = &fd_table[fd];
279 xstrncpy(F->desc, s, FD_DESC_SZ);
280 }
281
282 void
283 fd_bytes(int fd, int len, unsigned int type)
284 {
285 fde *F = &fd_table[fd];
286
287 if (len < 0)
288 return;
289
290 assert(type == FD_READ || type == FD_WRITE);
291
292 if (type == FD_READ)
293 F->bytes_read += len;
294 else
295 F->bytes_written += len;
296 }
297
298 void
299 fdDumpOpen(void)
300 {
301 int i;
302 fde *F;
303
304 for (i = 0; i < Squid_MaxFD; ++i) {
305 F = &fd_table[i];
306
307 if (!F->flags.open)
308 continue;
309
310 if (i == fileno(debug_log))
311 continue;
312
313 debugs(51, DBG_IMPORTANT, "Open FD "<< std::left<< std::setw(10) <<
314 (F->bytes_read && F->bytes_written ? "READ/WRITE" :
315 F->bytes_read ? "READING" : F->bytes_written ? "WRITING" :
316 "UNSTARTED") <<
317 " "<< std::right << std::setw(4) << i << " " << F->desc);
318 }
319 }
320
321 int
322 fdNFree(void)
323 {
324 return Squid_MaxFD - Number_FD - Opening_FD;
325 }
326
327 int
328 fdUsageHigh(void)
329 {
330 int nrfree = fdNFree();
331
332 if (nrfree < (RESERVED_FD << 1))
333 return 1;
334
335 if (nrfree < (Number_FD >> 2))
336 return 1;
337
338 return 0;
339 }
340
341 /* Called when we runs out of file descriptors */
342 void
343 fdAdjustReserved(void)
344 {
345 int newReserve;
346 int x;
347 static time_t last = 0;
348 /*
349 * don't update too frequently
350 */
351
352 if (last + 5 > squid_curtime)
353 return;
354
355 /*
356 * Calculate a new reserve, based on current usage and a small extra
357 */
358 newReserve = Squid_MaxFD - Number_FD + min(25, Squid_MaxFD / 16);
359
360 if (newReserve <= RESERVED_FD)
361 return;
362
363 x = Squid_MaxFD - 20 - min(25, Squid_MaxFD / 16);
364
365 if (newReserve > x) {
366 /* perhaps this should be fatal()? -DW */
367 debugs(51, DBG_CRITICAL, "WARNING: This machine has a serious shortage of filedescriptors.");
368 newReserve = x;
369 }
370
371 if (Squid_MaxFD - newReserve < min(256, Squid_MaxFD / 2))
372 fatalf("Too few filedescriptors available in the system (%d usable of %d).\n", Squid_MaxFD - newReserve, Squid_MaxFD);
373
374 debugs(51, DBG_CRITICAL, "Reserved FD adjusted from " << RESERVED_FD << " to " << newReserve << " due to failures");
375 RESERVED_FD = newReserve;
376 }