1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/epoll_server.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h>  // for abort
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h>    // for errno and strerror_r
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm>
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <iostream>
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <utility>
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector>
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/timer.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Design notes: An efficient implementation of ready list has the following
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// desirable properties:
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A. O(1) insertion into/removal from the list in any location.
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// B. Once the callback is found by hash lookup using the fd, the lookup of
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    corresponding entry in the list is O(1).
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// C. Safe insertion into/removal from the list during list iteration. (The
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    ready list's purpose is to enable completely event driven I/O model.
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    Thus, all the interesting bits happen in the callback. It is critical
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//    to not place any restriction on the API during list iteration.
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The current implementation achieves these goals with the following design:
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - The ready list is constructed as a doubly linked list to enable O(1)
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   insertion/removal (see man 3 queue).
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - The forward and backward links are directly embedded inside the
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   CBAndEventMask struct. This enables O(1) lookup in the list for a given
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   callback. (Techincally, we could've used std::list of hash_set::iterator,
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   and keep a list::iterator in CBAndEventMask to achieve the same effect.
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   However, iterators have two problems: no way to portably invalidate them,
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   and no way to tell whether an iterator is singular or not. The only way to
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   overcome these issues is to keep bools in both places, but that throws off
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   memory alignment (up to 7 wasted bytes for each bool). The extra level of
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   indirection will also likely be less cache friendly. Direct manipulation
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   of link pointers makes it easier to retrieve the CBAndEventMask from the
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   list, easier to check whether an CBAndEventMask is in the list, uses less
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   memory (save 32 bytes/fd), and does not affect cache usage (we need to
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   read in the struct to use the callback anyway).)
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Embed the fd directly into CBAndEventMask and switch to using hash_set.
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   This removes the need to store hash_map::iterator in the list just so that
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   we can get both the fd and the callback.
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - The ready list is "one shot": each entry is removed before OnEvent is
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   called. This removes the mutation-while-iterating problem.
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Use two lists to keep track of callbacks. The ready_list_ is the one used
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   for registration. Before iteration, the ready_list_ is swapped into the
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   tmp_list_. Once iteration is done, tmp_list_ will be empty, and
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//   ready_list_ will have all the new ready fds.
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The size we use for buffers passed to strerror_r
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kErrorBufferSize = 256;
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net {
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Clears the pipe and returns.  Used for waking the epoll server up.
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ReadPipeCallback : public EpollCallbackInterface {
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnEvent(int fd, EpollEvent* event) {
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(event->in_events == EPOLLIN);
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int data;
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int data_read = 1;
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Read until the pipe is empty.
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    while (data_read > 0) {
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      data_read = read(fd, &data, sizeof(data));
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnShutdown(EpollServer *eps, int fd) {}
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnRegistration(EpollServer*, int, int) {}
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnModification(int, int) {}       // COV_NF_LINE
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void OnUnregistration(int, bool) {}    // COV_NF_LINE
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////////////////////////////////////////////
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////////////////////////////////////////////
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollServer::EpollServer()
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  : epoll_fd_(epoll_create(1024)),
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    timeout_in_us_(0),
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    recorded_now_in_us_(0),
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ready_list_size_(0),
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    wake_cb_(new ReadPipeCallback),
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_fd_(-1),
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    write_fd_(-1),
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    in_wait_for_events_and_execute_callbacks_(false),
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    in_shutdown_(false) {
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ensure that the epoll_fd_ is valid.
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK_NE(epoll_fd_, -1);
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LIST_INIT(&ready_list_);
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LIST_INIT(&tmp_list_);
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int pipe_fds[2];
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (pipe(pipe_fds) < 0) {
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Unfortunately, it is impossible to test any such initialization in
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // a constructor (as virtual methods do not yet work).
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // This -could- be solved by moving initialization to an outside
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // call...
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int saved_errno = errno;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char buf[kErrorBufferSize];
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(FATAL) << "Error " << saved_errno
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << " in pipe(): " << strerror_r(saved_errno, buf, sizeof(buf));
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_fd_ = pipe_fds[0];
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  write_fd_ = pipe_fds[1];
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RegisterFD(read_fd_, wake_cb_.get(), EPOLLIN);
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CleanupFDToCBMap() {
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::iterator cb_iter = cb_map_.begin();
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (cb_iter != cb_map_.end()) {
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int fd = cb_iter->fd;
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CB* cb = cb_iter->cb;
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cb_iter->in_use = true;
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (cb) {
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cb->OnShutdown(this, fd);
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cb_map_.erase(cb_iter);
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cb_iter = cb_map_.begin();
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CleanupTimeToAlarmCBMap() {
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TimeToAlarmCBMap::iterator erase_it;
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Call OnShutdown() on alarms. Note that the structure of the loop
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // is similar to the structure of loop in the function HandleAlarms()
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (TimeToAlarmCBMap::iterator i = alarm_map_.begin();
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       i != alarm_map_.end();
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ) {
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Note that OnShutdown() can call UnregisterAlarm() on
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // other iterators. OnShutdown() should not call UnregisterAlarm()
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // on self because by definition the iterator is not valid any more.
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    i->second->OnShutdown(this);
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    erase_it = i;
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++i;
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    alarm_map_.erase(erase_it);
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollServer::~EpollServer() {
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(in_shutdown_, false);
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  in_shutdown_ = true;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(INFO) << "\n" << event_recorder_;
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VLOG(2) << "Shutting down epoll server ";
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CleanupFDToCBMap();
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LIST_INIT(&ready_list_);
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LIST_INIT(&tmp_list_);
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CleanupTimeToAlarmCBMap();
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  close(read_fd_);
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  close(write_fd_);
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  close(epoll_fd_);
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Whether a CBAandEventMask is on the ready list is determined by a non-NULL
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// le_prev pointer (le_next being NULL indicates end of list).
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline void EpollServer::AddToReadyList(CBAndEventMask* cb_and_mask) {
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cb_and_mask->entry.le_prev == NULL) {
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LIST_INSERT_HEAD(&ready_list_, cb_and_mask, entry);
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++ready_list_size_;
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline void EpollServer::RemoveFromReadyList(
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const CBAndEventMask& cb_and_mask) {
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cb_and_mask.entry.le_prev != NULL) {
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LIST_REMOVE(&cb_and_mask, entry);
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Clean up all the ready list states. Don't bother with the other fields
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // as they are initialized when the CBAandEventMask is added to the ready
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // list. This saves a few cycles in the inner loop.
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cb_and_mask.entry.le_prev = NULL;
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    --ready_list_size_;
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (ready_list_size_ == 0) {
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK(ready_list_.lh_first == NULL);
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK(tmp_list_.lh_first == NULL);
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFD(int fd, CB* cb, int event_mask) {
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(cb);
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VLOG(3) << "RegisterFD fd=" << fd << " event_mask=" << event_mask;
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cb_map_.end() != fd_i) {
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // do we just abort, or do we just unregister the other guy?
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // for now, lets just unregister the other guy.
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // unregister any callback that may already be registered for this FD.
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CB* other_cb = fd_i->cb;
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (other_cb) {
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Must remove from the ready list before erasing.
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      RemoveFromReadyList(*fd_i);
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      other_cb->OnUnregistration(fd, true);
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ModFD(fd, event_mask);
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // already unregistered, so just recycle the node.
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      AddFD(fd, event_mask);
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_i->cb = cb;
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_i->event_mask = event_mask;
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_i->events_to_fake = 0;
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AddFD(fd, event_mask);
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cb_map_.insert(CBAndEventMask(cb, event_mask, fd));
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // set the FD to be non-blocking.
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetNonblocking(fd);
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cb->OnRegistration(this, fd, event_mask);
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint EpollServer::GetFlags(int fd) {
22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return fcntl(fd, F_GETFL, 0);
22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::SetNonblocking(int fd) {
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int flags = GetFlags(fd);
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (flags == -1) {
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int saved_errno = errno;
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char buf[kErrorBufferSize];
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(FATAL) << "Error " << saved_errno
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << " doing fcntl(" << fd << ", F_GETFL, 0): "
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << strerror_r(saved_errno, buf, sizeof(buf));
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!(flags & O_NONBLOCK)) {
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int saved_flags = flags;
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    flags = SetFlags(fd, flags | O_NONBLOCK);
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (flags == -1) {
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // bad.
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int saved_errno = errno;
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      char buf[kErrorBufferSize];
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(FATAL) << "Error " << saved_errno
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        << " doing fcntl(" << fd << ", F_SETFL, " << saved_flags << "): "
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        << strerror_r(saved_errno, buf, sizeof(buf));
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint EpollServer::epoll_wait_impl(int epfd,
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 struct epoll_event* events,
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 int max_events,
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                 int timeout_in_ms) {
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return epoll_wait(epfd, events, max_events, timeout_in_ms);
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFDForWrite(int fd, CB* cb) {
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RegisterFD(fd, cb, EPOLLOUT);
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFDForReadWrite(int fd, CB* cb) {
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RegisterFD(fd, cb, EPOLLIN | EPOLLOUT);
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFDForRead(int fd, CB* cb) {
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RegisterFD(fd, cb, EPOLLIN);
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::UnregisterFD(int fd) {
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cb_map_.end() == fd_i || fd_i->cb == NULL) {
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Doesn't exist in server, or has gone through UnregisterFD once and still
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // inside the callchain of OnEvent.
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_recorder_.RecordUnregistration(fd);
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CB* cb = fd_i->cb;
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Since the links are embedded within the struct, we must remove it from the
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // list before erasing it from the hash_set.
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RemoveFromReadyList(*fd_i);
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DelFD(fd);
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cb->OnUnregistration(fd, false);
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // fd_i->cb is NULL if that fd is unregistered inside the callchain of
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // OnEvent. Since the EpollServer needs a valid CBAndEventMask after OnEvent
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // returns in order to add it to the ready list, we cannot have UnregisterFD
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // erase the entry if it is in use. Thus, a NULL fd_i->cb is used as a
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // condition that tells the EpollServer that this entry is unused at a later
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // point.
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!fd_i->in_use) {
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cb_map_.erase(fd_i);
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Remove all trace of the registration, and just keep the node alive long
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // enough so the code that calls OnEvent doesn't have to worry about
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // figuring out whether the CBAndEventMask is valid or not.
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_i->cb = NULL;
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_i->event_mask = 0;
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_i->events_to_fake = 0;
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::ModifyCallback(int fd, int event_mask) {
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ModifyFD(fd, ~0, event_mask);
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StopRead(int fd) {
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ModifyFD(fd, EPOLLIN, 0);
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StartRead(int fd) {
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ModifyFD(fd, 0, EPOLLIN);
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StopWrite(int fd) {
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ModifyFD(fd, EPOLLOUT, 0);
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StartWrite(int fd) {
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ModifyFD(fd, 0, EPOLLOUT);
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::HandleEvent(int fd, int event_mask) {
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_recorder_.RecordEpollEvent(fd, event_mask);
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (fd_i == cb_map_.end() || fd_i->cb == NULL) {
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Ignore the event.
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // This could occur if epoll() returns a set of events, and
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // while processing event A (earlier) we removed the callback
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // for event B (and are now processing event B).
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  fd_i->events_asserted = event_mask;
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CBAndEventMask* cb_and_mask = const_cast<CBAndEventMask*>(&*fd_i);
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddToReadyList(cb_and_mask);
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass TrueFalseGuard {
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit TrueFalseGuard(bool* guarded_bool) : guarded_bool_(guarded_bool) {
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(guarded_bool_ != NULL);
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(*guarded_bool_ == false);
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *guarded_bool_ = true;
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~TrueFalseGuard() {
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *guarded_bool_ = false;
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool* guarded_bool_;
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::WaitForEventsAndExecuteCallbacks() {
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (in_wait_for_events_and_execute_callbacks_) {
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(DFATAL) <<
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      "Attempting to call WaitForEventsAndExecuteCallbacks"
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      " when an ancestor to the current function is already"
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      " WaitForEventsAndExecuteCallbacks!";
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The line below is actually tested, but in coverage mode,
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // we never see it.
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;  // COV_NF_LINE
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TrueFalseGuard recursion_guard(&in_wait_for_events_and_execute_callbacks_);
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (alarm_map_.empty()) {
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // no alarms, this is business as usual.
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    WaitForEventsAndCallHandleEvents(timeout_in_us_,
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     events_,
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                     events_size_);
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    recorded_now_in_us_ = 0;
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // store the 'now'. If we recomputed 'now' every iteration
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // down below, then we might never exit that loop-- any
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // long-running alarms might install other long-running
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // alarms, etc. By storing it here now, we ensure that
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // a more reasonable amount of work is done here.
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 now_in_us  = NowInUsec();
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get the first timeout from the alarm_map where it is
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // stored in absolute time.
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 next_alarm_time_in_us =  alarm_map_.begin()->first;
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VLOG(4) << "next_alarm_time = " << next_alarm_time_in_us
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          << " now             = " << now_in_us
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          << " timeout_in_us = " << timeout_in_us_;
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 wait_time_in_us;
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 alarm_timeout_in_us = next_alarm_time_in_us - now_in_us;
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the next alarm is sooner than the default timeout, or if there is no
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // timeout (timeout_in_us_ == -1), wake up when the alarm should fire.
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Otherwise use the default timeout.
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (alarm_timeout_in_us < timeout_in_us_ || timeout_in_us_ < 0) {
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    wait_time_in_us = std::max(alarm_timeout_in_us, static_cast<int64>(0));
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    wait_time_in_us = timeout_in_us_;
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VLOG(4) << "wait_time_in_us = " << wait_time_in_us;
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // wait for events.
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WaitForEventsAndCallHandleEvents(wait_time_in_us,
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   events_,
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   events_size_);
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CallAndReregisterAlarmEvents();
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  recorded_now_in_us_ = 0;
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::SetFDReady(int fd, int events_to_fake) {
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cb_map_.end() != fd_i && fd_i->cb != NULL) {
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // This const_cast is necessary for LIST_HEAD_INSERT to work. Declaring
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // entry mutable is insufficient because LIST_HEAD_INSERT assigns the
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // forward pointer of the list head to the current cb_and_mask, and the
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // compiler complains that it can't assign a const T* to a T*.
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CBAndEventMask* cb_and_mask = const_cast<CBAndEventMask*>(&*fd_i);
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Note that there is no clearly correct behavior here when
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // cb_and_mask->events_to_fake != 0 and this function is called.
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Of the two operations:
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //      cb_and_mask->events_to_fake = events_to_fake
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //      cb_and_mask->events_to_fake |= events_to_fake
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // the first was picked because it discourages users from calling
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // SetFDReady repeatedly to build up the correct event set as it is more
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // efficient to call SetFDReady once with the correct, final mask.
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    cb_and_mask->events_to_fake = events_to_fake;
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AddToReadyList(cb_and_mask);
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::SetFDNotReady(int fd) {
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cb_map_.end() != fd_i) {
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RemoveFromReadyList(*fd_i);
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EpollServer::IsFDReady(int fd) const {
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::const_iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return (cb_map_.end() != fd_i &&
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          fd_i->cb != NULL &&
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          fd_i->entry.le_prev != NULL);
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::VerifyReadyList() const {
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int count = 0;
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CBAndEventMask* cur = ready_list_.lh_first;
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (; cur; cur = cur->entry.le_next) {
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++count;
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (cur = tmp_list_.lh_first; cur; cur = cur->entry.le_next) {
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++count;
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK_EQ(ready_list_size_, count) << "Ready list size does not match count";
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterAlarm(int64 timeout_time_in_us, AlarmCB* ac) {
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(ac);
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ContainsAlarm(ac)) {
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(FATAL) << "Alarm already exists " << ac;
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VLOG(4) << "RegisteringAlarm at : " << timeout_time_in_us;
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TimeToAlarmCBMap::iterator alarm_iter =
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      alarm_map_.insert(std::make_pair(timeout_time_in_us, ac));
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  all_alarms_.insert(ac);
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Pass the iterator to the EpollAlarmCallbackInterface.
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ac->OnRegistration(alarm_iter, this);
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unregister a specific alarm callback: iterator_token must be a
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//  valid iterator. The caller must ensure the validity of the iterator.
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::UnregisterAlarm(const AlarmRegToken& iterator_token) {
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AlarmCB* cb = iterator_token->second;
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  alarm_map_.erase(iterator_token);
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  all_alarms_.erase(cb);
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cb->OnUnregistration();
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint EpollServer::NumFDsRegistered() const {
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(cb_map_.size() >= 1);
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Omit the internal FD (read_fd_)
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return cb_map_.size() - 1;
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::Wake() {
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char data = 'd';  // 'd' is for data.  It's good enough for me.
491201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int rv = write(write_fd_, &data, 1);
492201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(rv == 1);
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 EpollServer::NowInUsec() const {
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return base::Time::Now().ToInternalValue();
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint64 EpollServer::ApproximateNowInUsec() const {
50072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (recorded_now_in_us_ != 0) {
50172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return recorded_now_in_us_;
50272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return this->NowInUsec();
50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string EpollServer::EventMaskToString(int event_mask) {
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string s;
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLIN) s += "EPOLLIN ";
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLPRI) s += "EPOLLPRI ";
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLOUT) s += "EPOLLOUT ";
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLRDNORM) s += "EPOLLRDNORM ";
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLRDBAND) s += "EPOLLRDBAND ";
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLWRNORM) s += "EPOLLWRNORM ";
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLWRBAND) s += "EPOLLWRBAND ";
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLMSG) s += "EPOLLMSG ";
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLERR) s += "EPOLLERR ";
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLHUP) s += "EPOLLHUP ";
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLONESHOT) s += "EPOLLONESHOT ";
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (event_mask & EPOLLET) s += "EPOLLET ";
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return s;
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::LogStateOnCrash() {
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << "----------------------Epoll Server---------------------------";
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << "Epoll server " << this << " polling on fd " << epoll_fd_;
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << "timeout_in_us_: " << timeout_in_us_;
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Log sessions with alarms.
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << alarm_map_.size() << " alarms registered.";
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (TimeToAlarmCBMap::iterator it = alarm_map_.begin();
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != alarm_map_.end();
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       ++it) {
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const bool skipped =
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        alarms_reregistered_and_should_be_skipped_.find(it->second)
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        != alarms_reregistered_and_should_be_skipped_.end();
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "Alarm " << it->second << " registered at time " << it->first
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << " and should be skipped = " << skipped;
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << cb_map_.size() << " fd callbacks registered.";
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (FDToCBMap::iterator it = cb_map_.begin();
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       it != cb_map_.end();
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       ++it) {
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "fd: " << it->fd << " with mask " << it->event_mask
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << " registered with cb: " << it->cb;
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LOG(ERROR) << "----------------------/Epoll Server--------------------------";
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////////////////////////////////////////////
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////////////////////////////////////////////
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::DelFD(int fd) const {
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct epoll_event ee;
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&ee, 0, sizeof(ee));
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_recorder_.RecordFDMaskEvent(fd, 0, "DelFD");
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &ee)) {
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int saved_errno = errno;
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char buf[kErrorBufferSize];
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(FATAL) << "Epoll set removal error for fd " << fd << ": "
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << strerror_r(saved_errno, buf, sizeof(buf));
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::AddFD(int fd, int event_mask) const {
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct epoll_event ee;
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&ee, 0, sizeof(ee));
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ee.events = event_mask | EPOLLERR | EPOLLHUP;
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ee.data.fd = fd;
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_recorder_.RecordFDMaskEvent(fd, ee.events, "AddFD");
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ee)) {
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int saved_errno = errno;
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char buf[kErrorBufferSize];
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(FATAL) << "Epoll set insertion error for fd " << fd << ": "
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << strerror_r(saved_errno, buf, sizeof(buf));
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::ModFD(int fd, int event_mask) const {
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  struct epoll_event ee;
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(&ee, 0, sizeof(ee));
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ee.events = event_mask | EPOLLERR | EPOLLHUP;
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ee.data.fd = fd;
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_recorder_.RecordFDMaskEvent(fd, ee.events, "ModFD");
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VLOG(3) <<  "modifying fd= " << fd << " "
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          << EventMaskToString(ee.events);
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &ee)) {
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int saved_errno = errno;
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    char buf[kErrorBufferSize];
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(FATAL) << "Epoll set modification error for fd " << fd << ": "
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << strerror_r(saved_errno, buf, sizeof(buf));
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::ModifyFD(int fd, int remove_event, int add_event) {
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd));
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (cb_map_.end() == fd_i) {
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VLOG(2) << "Didn't find the fd " << fd << "in internal structures";
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (fd_i->cb != NULL) {
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int & event_mask = fd_i->event_mask;
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VLOG(3) << "fd= " << fd
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott            << " event_mask before: " << EventMaskToString(event_mask);
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    event_mask &= ~remove_event;
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    event_mask |= add_event;
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VLOG(3) << " event_mask after: " << EventMaskToString(event_mask);
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ModFD(fd, event_mask);
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    fd_i->cb->OnModification(fd, event_mask);
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::WaitForEventsAndCallHandleEvents(int64 timeout_in_us,
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                   struct epoll_event events[],
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                   int events_size) {
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (timeout_in_us == 0 || ready_list_.lh_first != NULL) {
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If ready list is not empty, then don't sleep at all.
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    timeout_in_us = 0;
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (timeout_in_us < 0) {
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(INFO) << "Negative epoll timeout: " << timeout_in_us
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              << "us; epoll will wait forever for events.";
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If timeout_in_us is < 0 we are supposed to Wait forever.  This means we
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // should set timeout_in_us to -1000 so we will
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Wait(-1000/1000) == Wait(-1) == Wait forever.
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    timeout_in_us = -1000;
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If timeout is specified, and the ready list is empty.
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (timeout_in_us < 1000) {
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      timeout_in_us = 1000;
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int timeout_in_ms = timeout_in_us / 1000;
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int nfds = epoll_wait_impl(epoll_fd_,
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             events,
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             events_size,
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             timeout_in_ms);
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VLOG(3) << "nfds=" << nfds;
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  event_recorder_.RecordEpollWaitEvent(timeout_in_ms, nfds);
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If you're wondering why the NowInUsec() is recorded here, the answer is
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // simple: If we did it before the epoll_wait_impl, then the max error for
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // the ApproximateNowInUs() call would be as large as the maximum length of
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // epoll_wait, which can be arbitrarily long. Since this would make
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // ApproximateNowInUs() worthless, we instead record the time -after- we've
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // done epoll_wait, which guarantees that the maximum error is the amount of
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // time it takes to process all the events generated by epoll_wait.
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  recorded_now_in_us_ = NowInUsec();
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (nfds > 0) {
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int i = 0; i < nfds; ++i) {
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int event_mask = events[i].events;
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int fd = events[i].data.fd;
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      HandleEvent(fd, event_mask);
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (nfds < 0) {
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Catch interrupted syscall and just ignore it and move on.
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (errno != EINTR && errno != 0) {
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int saved_errno = errno;
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      char buf[kErrorBufferSize];
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(FATAL) << "Error " << saved_errno << " in epoll_wait: "
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 << strerror_r(saved_errno, buf, sizeof(buf));
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Now run through the ready list.
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (ready_list_.lh_first) {
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CallReadyListCallbacks();
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CallReadyListCallbacks() {
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check pre-conditions.
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(tmp_list_.lh_first == NULL);
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Swap out the ready_list_ into the tmp_list_ before traversing the list to
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // enable SetFDReady() to just push new items into the ready_list_.
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::swap(ready_list_.lh_first, tmp_list_.lh_first);
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (tmp_list_.lh_first) {
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    tmp_list_.lh_first->entry.le_prev = &tmp_list_.lh_first;
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EpollEvent event(0, false);
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    while (tmp_list_.lh_first != NULL) {
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK_GT(ready_list_size_, 0);
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      CBAndEventMask* cb_and_mask = tmp_list_.lh_first;
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      RemoveFromReadyList(*cb_and_mask);
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      event.out_ready_mask = 0;
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      event.in_events =
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cb_and_mask->events_asserted | cb_and_mask->events_to_fake;
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // TODO(fenix): get rid of the two separate fields in cb_and_mask.
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cb_and_mask->events_asserted = 0;
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cb_and_mask->events_to_fake = 0;
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      {
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // OnEvent() may call UnRegister, so we set in_use, here. Any
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // UnRegister call will now simply set the cb to NULL instead of
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // invalidating the cb_and_mask object (by deleting the object in the
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        // map to which cb_and_mask refers)
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        TrueFalseGuard in_use_guard(&(cb_and_mask->in_use));
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cb_and_mask->cb->OnEvent(cb_and_mask->fd, &event);
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Since OnEvent may have called UnregisterFD, we must check here that
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // the callback is still valid. If it isn't, then UnregisterFD *was*
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // called, and we should now get rid of the object.
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (cb_and_mask->cb == NULL) {
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cb_map_.erase(*cb_and_mask);
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else if (event.out_ready_mask != 0) {
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        cb_and_mask->events_to_fake = event.out_ready_mask;
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        AddToReadyList(cb_and_mask);
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(tmp_list_.lh_first == NULL);
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int EpollServer::kMinimumEffectiveAlarmQuantum = 1000;
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Alarms may be up to kMinimumEffectiveAlarmQuantum -1 us late.
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline int64 EpollServer::DoRoundingOnNow(int64 now_in_us) const {
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  now_in_us /= kMinimumEffectiveAlarmQuantum;
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  now_in_us *= kMinimumEffectiveAlarmQuantum;
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  now_in_us += (2 * kMinimumEffectiveAlarmQuantum - 1);
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return now_in_us;
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CallAndReregisterAlarmEvents() {
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int64 now_in_us = recorded_now_in_us_;
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(0, recorded_now_in_us_);
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  now_in_us = DoRoundingOnNow(now_in_us);
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  TimeToAlarmCBMap::iterator erase_it;
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // execute alarms.
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (TimeToAlarmCBMap::iterator i = alarm_map_.begin();
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott       i != alarm_map_.end();
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ) {
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (i->first > now_in_us) {
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    AlarmCB* cb = i->second;
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Execute the OnAlarm() only if we did not register
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // it in this loop itself.
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const bool added_in_this_round =
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        alarms_reregistered_and_should_be_skipped_.find(cb)
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        != alarms_reregistered_and_should_be_skipped_.end();
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (added_in_this_round) {
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ++i;
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    all_alarms_.erase(cb);
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const int64 new_timeout_time_in_us = cb->OnAlarm();
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    erase_it = i;
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ++i;
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    alarm_map_.erase(erase_it);
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (new_timeout_time_in_us > 0) {
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // We add to hash_set only if the new timeout is <= now_in_us.
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // if timeout is > now_in_us then we have no fear that this alarm
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // can be reexecuted in this loop, and hence we do not need to
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // worry about a recursive loop.
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DVLOG(3) << "Reregistering alarm "
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << " " << cb
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << " " << new_timeout_time_in_us
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               << " " << now_in_us;
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (new_timeout_time_in_us <= now_in_us) {
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        alarms_reregistered_and_should_be_skipped_.insert(cb);
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      RegisterAlarm(new_timeout_time_in_us, cb);
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  alarms_reregistered_and_should_be_skipped_.clear();
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollAlarm::EpollAlarm() : eps_(NULL), registered_(false) {
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollAlarm::~EpollAlarm() {
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  UnregisterIfRegistered();
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 EpollAlarm::OnAlarm() {
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  registered_ = false;
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return 0;
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::OnRegistration(const EpollServer::AlarmRegToken& token,
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                EpollServer* eps) {
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_EQ(false, registered_);
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  token_ = token;
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eps_ = eps;
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  registered_ = true;
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::OnUnregistration() {
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  registered_ = false;
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::OnShutdown(EpollServer* eps) {
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  registered_ = false;
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eps_ = NULL;
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If the alarm was registered, unregister it.
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::UnregisterIfRegistered() {
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!registered_) {
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  eps_->UnregisterAlarm(token_);
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace net
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
833