1
#pragma once
2

            
3
#include <chrono>
4
#include <functional>
5
#include <vector>
6

            
7
#include "envoy/common/time.h"
8
#include "envoy/config/listener/v3/listener.pb.h"
9
#include "envoy/event/dispatcher.h"
10
#include "envoy/event/timer.h"
11
#include "envoy/server/drain_manager.h"
12
#include "envoy/server/instance.h"
13

            
14
#include "source/common/common/callback_impl.h"
15
#include "source/common/common/logger.h"
16

            
17
namespace Envoy {
18
namespace Server {
19

            
20
/**
21
 * Implementation of drain manager that does the following by default:
22
 * 1) Terminates the parent process after 15 minutes.
23
 * 2) Drains the parent process over a period of 10 minutes where drain close becomes more
24
 *    likely each second that passes.
25
 */
26
class DrainManagerImpl : Logger::Loggable<Logger::Id::main>, public DrainManager {
27
public:
28
  DrainManagerImpl(Instance& server, envoy::config::listener::v3::Listener::DrainType drain_type,
29
                   Event::Dispatcher& dispatcher);
30

            
31
  // Network::DrainDecision
32
  bool drainClose(Network::DrainDirection scope) const override;
33
  Common::CallbackHandlePtr addOnDrainCloseCb(Network::DrainDirection direction,
34
                                              DrainCloseCb cb) const override;
35

            
36
  // Server::DrainManager
37
  void startDrainSequence(Network::DrainDirection direction,
38
                          std::function<void()> drain_complete_cb) override;
39
40
  bool draining(Network::DrainDirection direction) const override {
40
40
    auto drain_pair = draining_.load();
41
40
    return drain_pair.first && direction <= drain_pair.second;
42
40
  }
43
  void startParentShutdownSequence() override;
44
  DrainManagerPtr
45
  createChildManager(Event::Dispatcher& dispatcher,
46
                     envoy::config::listener::v3::Listener::DrainType drain_type) override;
47
  DrainManagerPtr createChildManager(Event::Dispatcher& dispatcher) override;
48

            
49
private:
50
  void addDrainCompleteCallback(Network::DrainDirection direction, std::function<void()> cb);
51

            
52
  Instance& server_;
53
  Event::Dispatcher& dispatcher_;
54
  const envoy::config::listener::v3::Listener::DrainType drain_type_;
55
  using DrainPair = struct {
56
    bool first;
57
    Network::DrainDirection second;
58
  };
59
  std::atomic<DrainPair> draining_{DrainPair{false, Network::DrainDirection::None}};
60
  // A map of timers keyed by the direction that triggered the drain
61
  std::map<Network::DrainDirection, Event::TimerPtr> drain_tick_timers_;
62
  std::map<Network::DrainDirection, MonotonicTime> drain_deadlines_ = {
63
      {Network::DrainDirection::InboundOnly, MonotonicTime()},
64
      {Network::DrainDirection::All, MonotonicTime()}};
65
  mutable Common::CallbackManager<absl::Status, std::chrono::milliseconds> cbs_{};
66
  std::vector<std::function<void()>> drain_complete_cbs_;
67

            
68
  // Callbacks called by startDrainSequence to cascade/proxy to children
69
  std::shared_ptr<Common::ThreadSafeCallbackManager> children_;
70

            
71
  // Callback handle parent will invoke to initiate drain-sequence. Created and set
72
  // by the parent drain-manager.
73
  Common::CallbackHandlePtr parent_callback_handle_;
74

            
75
  Event::TimerPtr parent_shutdown_timer_;
76
};
77

            
78
} // namespace Server
79
} // namespace Envoy