kinetic-c  v0.12.0
Seagate Kinetic Protocol Client Library for C
bus_poll.c
Go to the documentation of this file.
1 /*
2 * kinetic-c
3 * Copyright (C) 2015 Seagate Technology.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20 #include "bus_poll.h"
21 #include "syscall.h"
22 #include "listener.h"
23 #include "util.h"
24 
25 #include <assert.h>
26 #include <errno.h>
27 
28 #ifdef TEST
29 struct pollfd fds[1];
30 uint8_t read_buf[sizeof(uint8_t) + sizeof(uint16_t)];
31 int poll_errno;
32 int read_errno;
33 #endif
34 
35 bool BusPoll_OnCompletion(struct bus *b, int fd) {
36  /* POLL in a pipe */
37  #ifndef TEST
38  struct pollfd fds[1];
39  #endif
40  fds[0].fd = fd;
41  fds[0].events = POLLIN;
42 
43  for (;;) {
44  BUS_LOG(b, 5, LOG_SENDING_REQUEST, "Polling on completion...tick...", b->udata);
45  #ifdef TEST
46  errno = poll_errno;
47  #endif
49  "poll_on_completion, polling %d", fd);
50  int res = syscall_poll(fds, 1, -1);
52  "poll_on_completion for %d, res %d (errno %d)", fd, res, errno);
53  if (res == -1) {
54  if (Util_IsResumableIOError(errno)) {
56  "poll_on_completion, resumable IO error %d", errno);
57  errno = 0;
58  continue;
59  } else {
61  "poll_on_completion, non-resumable IO error %d", errno);
62  return false;
63  }
64  } else if (res == 1) {
65  uint16_t msec = 0;
66  #ifndef TEST
67  uint8_t read_buf[sizeof(uint8_t) + sizeof(uint16_t)];
68  #endif
69 
70  if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
71  BUS_LOG(b, 1, LOG_SENDING_REQUEST, "failed (broken alert pipe)", b->udata);
72  return false;
73  }
74 
75  BUS_LOG(b, 3, LOG_SENDING_REQUEST, "Reading alert pipe...", b->udata);
76  #ifdef TEST
77  errno = read_errno;
78  #endif
79  ssize_t sz = syscall_read(fd, read_buf, sizeof(read_buf));
80 
81  if (sz == sizeof(read_buf)) {
82  /* Payload: little-endian uint16_t, msec of backpressure. */
83  assert(read_buf[0] == LISTENER_MSG_TAG);
84 
85  msec = (read_buf[1] << 0) + (read_buf[2] << 8);
87  BUS_LOG(b, 4, LOG_SENDING_REQUEST, "sent!", b->udata);
88  return true;
89  } else if (sz == -1) {
90  if (Util_IsResumableIOError(errno)) {
92  "poll_on_completion read, resumable IO error %d", errno);
93  errno = 0;
94  continue;
95  } else {
97  "poll_on_completion read, non-resumable IO error %d", errno);
98  errno = 0;
99  return false;
100  }
101  } else {
103  "poll_on_completion bad read size %zd", sz);
104  return false;
105  }
106  } else {
107  /* This should never happen, but I have seen it occur on OSX.
108  * If we log it, reset errno, and continue, it does not appear
109  * to fall into busywaiting by always returning 0. */
111  "poll_on_completion, blocking forever returned %d, errno %d", res, errno);
112  errno = 0;
113  }
114  }
115 }
bool Util_IsResumableIOError(int errno_)
Definition: util.c:26
#define LISTENER_BACKPRESSURE_SHIFT
How many bits to >> the backpressure value from commands delivered to the listener.
Definition: listener.h:28
#define LISTENER_MSG_TAG
Arbitrary byte used to tag writes from the listener.
static uint8_t read_buf[(2 *1024L *1024)]
Definition: echosrv.c:44
Message bus.
void * udata
User data for callbacks.
ssize_t syscall_read(int fildes, void *buf, size_t nbyte)
Definition: syscall.c:39
void Bus_BackpressureDelay(struct bus *b, size_t backpressure, uint8_t shift)
Provide backpressure by sleeping for (backpressure >> shift) msec, if the value is greater than 0...
Definition: bus.c:551
bool BusPoll_OnCompletion(struct bus *b, int fd)
Poll on fd until complete, return true on success or false on IO error.
Definition: bus_poll.c:35
#define BUS_LOG_SNPRINTF(B, LEVEL, EVENT_KEY, UDATA, MAX_SZ, FMT,...)
Definition: bus_types.h:59
int syscall_poll(struct pollfd fds[], nfds_t nfds, int timeout)
Wrappers for syscalls, to allow mocking for testing.
Definition: syscall.c:27
#define BUS_LOG(B, LEVEL, EVENT_KEY, MSG, UDATA)
Definition: bus_types.h:45