summaryrefslogtreecommitdiffstats
path: root/src/msg/Policy.h
blob: 0cfa03aee5701c197fde1985f175d5d26adfaf70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#pragma once

#include "include/ceph_features.h"

namespace ceph::net {

using peer_type_t = int;

/**
 * A Policy describes the rules of a Connection. Is there a limit on how
 * much data this Connection can have locally? When the underlying connection
 * experiences an error, does the Connection disappear? Can this Messenger
 * re-establish the underlying connection?
 */
template<class ThrottleType>
struct Policy {
  /// If true, the Connection is tossed out on errors.
  bool lossy;
  /// If true, the underlying connection can't be re-established from this end.
  bool server;
  /// If true, we will standby when idle
  bool standby;
  /// If true, we will try to detect session resets
  bool resetcheck;

  /// Server: register lossy client connections.
  bool register_lossy_clients = true;
  // The net result of this is that a given client can only have one
  // open connection with the server.  If a new connection is made,
  // the old (registered) one is closed by the messenger during the accept
  // process.
  
  /**
   *  The throttler is used to limit how much data is held by Messages from
   *  the associated Connection(s). When reading in a new Message, the Messenger
   *  will call throttler->throttle() for the size of the new Message.
   */
  ThrottleType* throttler_bytes;
  ThrottleType* throttler_messages;
  
  /// Specify features supported locally by the endpoint.
#ifdef MSG_POLICY_UNIT_TESTING
  uint64_t features_supported{CEPH_FEATURES_SUPPORTED_DEFAULT};
#else
  static constexpr uint64_t features_supported{CEPH_FEATURES_SUPPORTED_DEFAULT};
#endif

  /// Specify features any remotes must have to talk to this endpoint.
  uint64_t features_required;
  
  Policy()
    : lossy(false), server(false), standby(false), resetcheck(true),
      throttler_bytes(NULL),
      throttler_messages(NULL),
      features_required(0) {}
private:
  Policy(bool l, bool s, bool st, bool r, bool rlc, uint64_t req)
    : lossy(l), server(s), standby(st), resetcheck(r),
      register_lossy_clients(rlc),
      throttler_bytes(NULL),
      throttler_messages(NULL),
      features_required(req) {}
  
public:
  static Policy stateful_server(uint64_t req) {
    return Policy(false, true, true, true, true, req);
  }
  static Policy stateless_registered_server(uint64_t req) {
    return Policy(true, true, false, false, true, req);
  }
  static Policy stateless_server(uint64_t req) {
    return Policy(true, true, false, false, false, req);
  }
  static Policy lossless_peer(uint64_t req) {
    return Policy(false, false, true, false, true, req);
  }
  static Policy lossless_peer_reuse(uint64_t req) {
    return Policy(false, false, true, true, true, req);
  }
  static Policy lossy_client(uint64_t req) {
    return Policy(true, false, false, false, true, req);
  }
  static Policy lossless_client(uint64_t req) {
    return Policy(false, false, false, true, true, req);
  }
};

template<class ThrottleType>
class PolicySet {
  using policy_t = Policy<ThrottleType> ;
  /// the default Policy we use for Pipes
  policy_t default_policy;
  /// map specifying different Policies for specific peer types
  std::map<int, policy_t> policy_map; // entity_name_t::type -> Policy

public:
  const policy_t& get(peer_type_t peer_type) const {
    if (auto found = policy_map.find(peer_type); found != policy_map.end()) {
      return found->second;
    } else {
      return default_policy;
    }
  }
  policy_t& get(peer_type_t peer_type) {
    if (auto found = policy_map.find(peer_type); found != policy_map.end()) {
      return found->second;
    } else {
      return default_policy;
    }
  }
  void set(peer_type_t peer_type, const policy_t& p) {
    policy_map[peer_type] = p;
  }
  const policy_t& get_default() const {
    return default_policy;
  }
  void set_default(const policy_t& p) {
    default_policy = p;
  }
  void set_throttlers(peer_type_t peer_type,
                      ThrottleType* byte_throttle,
                      ThrottleType* msg_throttle) {
    auto& policy = get(peer_type);
    policy.throttler_bytes = byte_throttle;
    policy.throttler_messages = msg_throttle;
  }
};

}