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
|
// Copyright (C) 2020-2021 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef HA_LEASE_BACKLOG_H
#define HA_LEASE_BACKLOG_H
#include <dhcpsrv/lease.h>
#include <deque>
#include <mutex>
#include <utility>
namespace isc {
namespace ha {
/// @brief Queue holding a backlog of unsent lease updates.
///
/// Lease updates are appended to this queue when the service is in the
/// communication-recovery state. In this state, the server temporarily
/// lost communication with the partner and can't send lease updates.
/// The server keeps responding to DHCP queries but it must store unsent
/// lease updates and later send them when the communication is resumed.
/// The lease updates are stored in this queue.
///
/// This queue has configurable size. If the number of leases appended
/// to the queue reaches the limit, no more updates can be added to it.
/// This prevents inifinite growth of the queue and excessive memory
/// consumption.
///
/// There are two types of lease updates: "Add" and "Delete". The type
/// is specified when the lease is appended to the queue.
///
/// The backlog queue holds both "Add" and "Delete" lease updates in a
/// single std::deque container, which allows for ordering them
/// chronologically and using this ordering for queue optimizations in
/// the future. For example, if the queue contains consecutive "Delete"
/// updates for a particular IP address, the server could only delete
/// the lease once. If the queue contains multiple "Delete" lease updates
/// followed by an "Add" update, the server could skip sending "Delete"
/// updates.
///
/// Queue optimizations will be subject to future work!
class LeaseUpdateBacklog {
public:
/// @brief Type of the lease update (operation type).
enum OpType {
ADD,
DELETE
};
/// @brief Constructor.
///
/// @param limit specifies the maximum number of lease updates which
/// can be stored in the queue.
LeaseUpdateBacklog(const size_t limit);
/// @brief Appends lease update to the queue.
///
/// @param op_type type of the lease update (operation type).
/// @param lease pointer to the lease being added, or deleted.
/// @return boolean value indicating whether the lease was successfully
/// appended to the queue (if true) or not (if false).
bool push(const OpType op_type, const dhcp::LeasePtr& lease);
/// @brief Returns the next lease update and removes it from the queue.
///
/// @param [out] op_type reference to the value receiving lease update type.
/// @return pointer to the next lease update in the queue or null pointer
/// when the queue is empty.
dhcp::LeasePtr pop(OpType& op_type);
/// @brief Checks if the queue was overflown.
///
/// This method returns true if the number of lease updates exceeded
/// the queue size limit at any point. The HA service checks this
/// flag when the communication with the partner is resumed to make
/// decisions about lease synchronization. If the queue was not
/// overflown, the server will send lease updates which are sitting
/// in the queue. Otherwise, it will go over the fully blown lease
/// database synchronization process.
///
/// This flag is reset to false when @c clear is called.
///
/// @return true if the queue was overflown, false otherwise.
bool wasOverflown();
/// @brief Removes all lease updates from the queue.
///
/// It also resets the flag indicating that the queue was overflown.
void clear();
/// @brief Returns the current size of the queue.
size_t size();
private:
/// @brief Appends lease update to the queue (thread unsafe).
///
/// @param op_type type of the lease update (operation type).
/// @param lease pointer to the lease being added, or deleted.
/// @return boolean value indicating whether the lease was successfully
/// appended to the queue (if true) or not (if false).
bool pushInternal(const OpType op_type, const dhcp::LeasePtr& lease);
/// @brief Returns the next lease update and removes it from the queue (thread unsafe).
///
/// @param [out] op_type reference to the value receiving lease update type.
/// @return pointer to the next lease update in the queue or null pointer
/// when the queue is empty.
dhcp::LeasePtr popInternal(OpType& op_type);
/// @brief Holds the queue size limit.
size_t limit_;
/// @brief Remembers whether the queue was overflown.
bool overflown_;
/// @brief Actual queue of lease updates and their types.
std::deque<std::pair<OpType, dhcp::LeasePtr> > outstanding_updates_;
/// @brief Mutex to protect internal state.
std::mutex mutex_;
};
} // end of namespace isc::ha
} // end of namespace isc
#endif // HA_LEASE_BACKLOG_H
|