fd.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 51 Filedescriptor Functions */
10 
11 #include "squid.h"
12 #include "comm/Loops.h"
13 #include "Debug.h"
14 #include "fatal.h"
15 #include "fd.h"
16 #include "fde.h"
17 #include "globals.h"
18 #include "profiler/Profiler.h"
19 #include "SquidTime.h"
20 
21 // Solaris and possibly others lack MSG_NOSIGNAL optimization
22 // TODO: move this into compat/? Use a dedicated compat file to avoid dragging
23 // sys/socket.h into the rest of Squid??
24 #ifndef MSG_NOSIGNAL
25 #define MSG_NOSIGNAL 0
26 #endif
27 
28 int default_read_method(int, char *, int);
29 int default_write_method(int, const char *, int);
30 #if _SQUID_WINDOWS_
31 int socket_read_method(int, char *, int);
32 int socket_write_method(int, const char *, int);
33 int file_read_method(int, char *, int);
34 int file_write_method(int, const char *, int);
35 #else
36 int msghdr_read_method(int, char *, int);
37 int msghdr_write_method(int, const char *, int);
38 #endif
39 
40 const char *fdTypeStr[] = {
41  "None",
42  "Log",
43  "File",
44  "Socket",
45  "Pipe",
46  "MsgHdr",
47  "Unknown"
48 };
49 
50 static void fdUpdateBiggest(int fd, int);
51 
52 static void
53 fdUpdateBiggest(int fd, int opening)
54 {
55  if (fd < Biggest_FD)
56  return;
57 
58  assert(fd < Squid_MaxFD);
59 
60  if (fd > Biggest_FD) {
61  /*
62  * assert that we are not closing a FD bigger than
63  * our known biggest FD
64  */
65  assert(opening);
66  Biggest_FD = fd;
67  return;
68  }
69 
70  /* if we are here, then fd == Biggest_FD */
71  /*
72  * assert that we are closing the biggest FD; we can't be
73  * re-opening it
74  */
75  assert(!opening);
76 
77  while (Biggest_FD >= 0 && !fd_table[Biggest_FD].flags.open)
78  --Biggest_FD;
79 }
80 
81 void
82 fd_close(int fd)
83 {
84  fde *F = &fd_table[fd];
85 
86  assert(fd >= 0);
87  assert(F->flags.open);
88 
89  if (F->type == FD_FILE) {
90  assert(F->read_handler == NULL);
91  assert(F->write_handler == NULL);
92  }
93 
94  debugs(51, 3, "fd_close FD " << fd << " " << F->desc);
97  F->flags.open = false;
98  fdUpdateBiggest(fd, 0);
99  --Number_FD;
100  F->clear();
101 }
102 
103 #if _SQUID_WINDOWS_
104 
105 int
106 socket_read_method(int fd, char *buf, int len)
107 {
108  int i;
109  PROF_start(recv);
110  i = recv(fd, (void *) buf, len, 0);
111  PROF_stop(recv);
112  return i;
113 }
114 
115 int
116 file_read_method(int fd, char *buf, int len)
117 {
118  int i;
119  PROF_start(read);
120  i = _read(fd, buf, len);
121  PROF_stop(read);
122  return i;
123 }
124 
125 int
126 socket_write_method(int fd, const char *buf, int len)
127 {
128  int i;
129  PROF_start(send);
130  i = send(fd, (const void *) buf, len, 0);
131  PROF_stop(send);
132  return i;
133 }
134 
135 int
136 file_write_method(int fd, const char *buf, int len)
137 {
138  int i;
139  PROF_start(write);
140  i = (_write(fd, buf, len));
141  PROF_stop(write);
142  return i;
143 }
144 
145 #else
146 int
147 default_read_method(int fd, char *buf, int len)
148 {
149  int i;
150  PROF_start(read);
151  i = read(fd, buf, len);
152  PROF_stop(read);
153  return i;
154 }
155 
156 int
157 default_write_method(int fd, const char *buf, int len)
158 {
159  int i;
160  PROF_start(write);
161  i = write(fd, buf, len);
162  PROF_stop(write);
163  return i;
164 }
165 
166 int
167 msghdr_read_method(int fd, char *buf, int)
168 {
169  PROF_start(read);
170  const int i = recvmsg(fd, reinterpret_cast<msghdr*>(buf), MSG_DONTWAIT);
171  PROF_stop(read);
172  return i;
173 }
174 
175 int
176 msghdr_write_method(int fd, const char *buf, int len)
177 {
178  PROF_start(write);
179  const int i = sendmsg(fd, reinterpret_cast<const msghdr*>(buf), MSG_NOSIGNAL);
180  PROF_stop(write);
181  return i > 0 ? len : i; // len is imprecise but the caller expects a match
182 }
183 
184 #endif
185 
186 void
187 fd_open(int fd, unsigned int type, const char *desc)
188 {
189  fde *F;
190  assert(fd >= 0);
191  F = &fd_table[fd];
192 
193  if (F->flags.open) {
194  debugs(51, DBG_IMPORTANT, "WARNING: Closing open FD " << std::setw(4) << fd);
195  fd_close(fd);
196  }
197 
198  assert(!F->flags.open);
199  debugs(51, 3, "fd_open() FD " << fd << " " << desc);
200  F->type = type;
201  F->flags.open = true;
202  F->epoll_state = 0;
203 #if _SQUID_WINDOWS_
204 
205  F->win32.handle = _get_osfhandle(fd);
206 
207  switch (type) {
208 
209  case FD_SOCKET:
210 
211  case FD_PIPE:
212  F->read_method = &socket_read_method;
213  F->write_method = &socket_write_method;
214  break;
215 
216  case FD_FILE:
217 
218  case FD_LOG:
219  F->read_method = &file_read_method;
220  F->write_method = &file_write_method;
221  break;
222 
223  default:
224  fatalf("fd_open(): unknown FD type - FD#: %i, type: %u, desc %s\n", fd, type, desc);
225  }
226 
227 #else
228  switch (type) {
229 
230  case FD_MSGHDR:
233  break;
234 
235  default:
238  break;
239  }
240 
241 #endif
242 
243  fdUpdateBiggest(fd, 1);
244 
245  fd_note(fd, desc);
246 
247  ++Number_FD;
248 }
249 
250 void
251 fd_note(int fd, const char *s)
252 {
253  fde *F = &fd_table[fd];
254  if (s)
255  xstrncpy(F->desc, s, FD_DESC_SZ);
256  else
257  *(F->desc) = 0; // ""-string
258 }
259 
260 void
261 fd_bytes(int fd, int len, unsigned int type)
262 {
263  fde *F = &fd_table[fd];
264 
265  if (len < 0)
266  return;
267 
268  assert(type == FD_READ || type == FD_WRITE);
269 
270  if (type == FD_READ)
271  F->bytes_read += len;
272  else
273  F->bytes_written += len;
274 }
275 
276 void
278 {
279  int i;
280  fde *F;
281 
282  for (i = 0; i < Squid_MaxFD; ++i) {
283  F = &fd_table[i];
284 
285  if (!F->flags.open)
286  continue;
287 
288  if (i == fileno(debug_log))
289  continue;
290 
291  debugs(51, DBG_IMPORTANT, "Open FD "<< std::left<< std::setw(10) <<
292  (F->bytes_read && F->bytes_written ? "READ/WRITE" :
293  F->bytes_read ? "READING" : F->bytes_written ? "WRITING" :
294  "UNSTARTED") <<
295  " "<< std::right << std::setw(4) << i << " " << F->desc);
296  }
297 }
298 
299 int
300 fdNFree(void)
301 {
302  return Squid_MaxFD - Number_FD - Opening_FD;
303 }
304 
305 int
307 {
308  int nrfree = fdNFree();
309 
310  if (nrfree < (RESERVED_FD << 1))
311  return 1;
312 
313  if (nrfree < (Number_FD >> 2))
314  return 1;
315 
316  return 0;
317 }
318 
319 /* Called when we runs out of file descriptors */
320 void
322 {
323  int newReserve;
324  int x;
325  static time_t last = 0;
326  /*
327  * don't update too frequently
328  */
329 
330  if (last + 5 > squid_curtime)
331  return;
332 
333  /*
334  * Calculate a new reserve, based on current usage and a small extra
335  */
336  newReserve = Squid_MaxFD - Number_FD + min(25, Squid_MaxFD / 16);
337 
338  if (newReserve <= RESERVED_FD)
339  return;
340 
341  x = Squid_MaxFD - 20 - min(25, Squid_MaxFD / 16);
342 
343  if (newReserve > x) {
344  /* perhaps this should be fatal()? -DW */
345  debugs(51, DBG_CRITICAL, "WARNING: This machine has a serious shortage of filedescriptors.");
346  newReserve = x;
347  }
348 
349  if (Squid_MaxFD - newReserve < min(256, Squid_MaxFD / 2))
350  fatalf("Too few filedescriptors available in the system (%d usable of %d).\n", Squid_MaxFD - newReserve, Squid_MaxFD);
351 
352  debugs(51, DBG_CRITICAL, "Reserved FD adjusted from " << RESERVED_FD << " to " << newReserve <<
353  " due to failures (" << (Squid_MaxFD - newReserve) << "/" << Squid_MaxFD << " file descriptors available)");
354  RESERVED_FD = newReserve;
355 }
356 
int fdUsageHigh(void)
Definition: fd.cc:306
#define debug_log
change-avoidance macro; new code should call DebugStream() instead
Definition: Debug.h:106
#define fd_table
Definition: fde.h:157
#define COMM_SELECT_READ
Definition: defines.h:36
#define assert(EX)
Definition: assert.h:17
Definition: enums.h:14
int Squid_MaxFD
struct fde::_fde_flags flags
void fd_note(int fd, const char *s)
Definition: fd.cc:251
int type
Definition: errorpage.cc:79
int default_read_method(int, char *, int)
Definition: fd.cc:147
int i
Definition: membanger.c:49
void fd_open(int fd, unsigned int type, const char *desc)
Definition: fd.cc:187
static void fdUpdateBiggest(int fd, int)
Definition: fd.cc:53
static char last
Definition: parse.c:479
int64_t bytes_written
Definition: fde.h:112
Definition: enums.h:24
unsigned int type
Definition: fde.h:83
#define DBG_CRITICAL
Definition: Debug.h:44
const char * fdTypeStr[]
Definition: fd.cc:40
int fdNFree(void)
Definition: fd.cc:300
int default_write_method(int, const char *, int)
Definition: fd.cc:157
void fdAdjustReserved(void)
Definition: fd.cc:321
Definition: enums.h:23
PF * write_handler
Definition: fde.h:128
time_t squid_curtime
Definition: stub_time.cc:17
#define MSG_NOSIGNAL
Definition: fd.cc:25
void fatalf(const char *fmt,...)
Definition: fatal.cc:79
int RESERVED_FD
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:261
READ_HANDLER * read_method
read handler for half-closed fds
Definition: fde.h:136
int64_t bytes_read
Definition: fde.h:111
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
PF * read_handler
Definition: fde.h:126
#define DBG_IMPORTANT
Definition: Debug.h:45
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
Definition: ModDevPoll.cc:225
#define FD_DESC_SZ
Definition: defines.h:46
void fdDumpOpen(void)
Definition: fd.cc:277
#define COMM_SELECT_WRITE
Definition: defines.h:37
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
int Number_FD
int Biggest_FD
void fd_close(int fd)
Definition: fd.cc:82
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
int msghdr_read_method(int, char *, int)
Definition: fd.cc:167
Definition: enums.h:17
unsigned epoll_state
Definition: fde.h:123
#define PROF_start(probename)
Definition: Profiler.h:62
void clear()
Clear the fde class back to NULL equivalent.
Definition: fde.h:63
int Opening_FD
WRITE_HANDLER * write_method
Definition: fde.h:137
bool open
Definition: fde.h:96
Definition: fde.h:49
Definition: enums.h:15
static uint32 F(uint32 X, uint32 Y, uint32 Z)
Definition: md4.c:46
int msghdr_write_method(int, const char *, int)
Definition: fd.cc:176
#define PROF_stop(probename)
Definition: Profiler.h:63
char desc[FD_DESC_SZ]
Definition: fde.h:93
#define NULL
Definition: types.h:166
A const & min(A const &lhs, A const &rhs)

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors