MySQL 26.7.0
Source Code Documentation
clock_lwm_registry.h
Go to the documentation of this file.
1// Copyright (c) 2026, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is distributed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23
24#ifndef MYSQL_SCHEDULER_CLOCK_LWM_REGISTRY_H
25#define MYSQL_SCHEDULER_CLOCK_LWM_REGISTRY_H
26
27#include <atomic>
28#include <memory>
33
34namespace mysql::scheduler {
35
36/// @brief Clock implementation that computes LWM (Low Water Mark) based on
37/// executed tasks. This class provides a Scheduler_clock interface where the
38/// "time" is represented by the LWM, which can be defined in two equivalent
39/// ways:
40/// - The maximum task ID such that the task and all preceding tasks are
41/// completed.
42/// - The minimum task ID that is not completed, minus 1.
43///
44/// Internally, this class uses a Task_registry_multi to track the state of
45/// tasks (registered, started, finished). It maintains an atomic LWM value,
46/// updated when tasks finish execution via the tick() method. The LWM advances
47/// to the maximum ID where all tasks up to that ID are finished.
48///
49/// Key Identifiers (Internal to this Class):
50/// - Task_id: Opaque ID used in the Scheduler_clock API and internally.
51/// Assigned by the scheduler or caller; this class does not assign or
52/// translate IDs.
53/// - LWM (Low Water Mark): The current "time" value, starting at 0 and
54/// monotonically increasing.
55///
56/// Performance Characteristics:
57/// - Uses fine-grained locking with 16384 buckets in the Task_registry_multi.
58/// - Employs spin locks for low-latency synchronization in low-contention
59/// scenarios.
60///
61/// API Overview:
62/// - now(): Returns the current LWM.
63/// - start_time(): Returns 0 (initial LWM).
64/// - add_time(task_id, time_point): Registers a task at the given task_id. The
65/// time_point is ignored here.
66/// - tick(task_id, time_point): Marks the task as finished and updates LWM if
67/// possible. The time_point is ignored.
68/// - The class handles concurrency via atomics for LWM and per-bucket locking
69/// in the registry.
70///
71/// Relation to External Components (e.g., CSA):
72/// This class is designed for use in systems like Change Stream Apply (CSA),
73/// where:
74/// - CSA assigns Task_id identifiers to received transactions and computes a
75/// last committed task ID (the ID of the last transaction that must precede
76/// it).
77/// - Translation from source's parallel indexes to Task_id occurs outside this
78/// class (in CSA logic).
79/// - A CSA task registers with add_time and waits until now() >= it's LWM time
80/// - Upon finishing, it calls tick( on its task ID ).
81/// - This ensures causality: a transaction applies only after all tasks up to
82/// its LWM time has completed
83/// - LWM enables parallelism: tasks with higher IDs can proceed if LWM advances
84/// past lower ones.
86 public:
87 /// @brief Construct the clock - initializes the internal task registry
88 /// Since we use spin lock in this implementation, we skip PSI instrumentation
89 /// @param clock_capacity The maximum number of tasks this clock may
90 /// handle
91 /// @param psi_params Instrumentation
92 Clock_lwm_registry(std::size_t clock_capacity = 8192,
93 [[maybe_unused]] Scheduler_clock_psi psi_params = {})
94 : m_executed_registry(clock_capacity) {}
95
96 /// @brief Get the current value of the LWM
97 /// @return Current time (LWM)
98 Time_point_t now() const override;
99
100 /// @brief Get start time of this clock - the first LWM value (0)
101 /// @return Clock start time for the scheduler to know from which time
102 /// we calculate the task delay
103 Time_point_t start_time() const override;
104
105 /// @brief Registers a task to execute at specific LWM. Here, we don't need
106 /// to know at which LWM task executes.
107 /// @param task_id Id of the task that finished execution
108 /// @return True if task was registered successfully, false otherwise.
109 bool add_time(Task_id task_id, Time_point_t) override;
110
111 /// @brief Tick performed on the clock when task finishes
112 /// @param task_id Id of the task that finished execution
113 /// @return True if clock value changed, false otherwise.
114 bool tick(Task_id task_id, Time_point_t) override;
115
116 /// @brief Backdoor for unit tests to set LWM to a specific value
118
119 private:
120 /// This structure is used to represent a registered task state and update
121 /// LWM. After registration, the task stays active as long as LWM is lower
122 /// than the task ID. After LWM passes its ID (finished is equal to true),
123 /// task may be unregistered from the registry.
124 struct Task_state {
125 /// @brief Task has started
126 bool started = false;
127 /// @brief Task has finished
128 bool finished = false;
129 };
130
131 /// @brief Registry of executed tasks. Concurrency is covered by the
132 /// Task Registry Multi (handles id conflicts)
134 /// @brief Current LWM value
135 std::atomic<Time_point_t> m_current_lwm{0};
136};
137
138} // namespace mysql::scheduler
139
140#endif // MYSQL_SCHEDULER_CLOCK_LWM_REGISTRY_H
Clock implementation that computes LWM (Low Water Mark) based on executed tasks.
Definition: clock_lwm_registry.h:85
void test_set_current_lwm(Time_point_t lwm)
Backdoor for unit tests to set LWM to a specific value.
Definition: clock_lwm_registry.cpp:104
Clock_lwm_registry(std::size_t clock_capacity=8192, Scheduler_clock_psi psi_params={})
Construct the clock - initializes the internal task registry Since we use spin lock in this implement...
Definition: clock_lwm_registry.h:92
Time_point_t now() const override
Get the current value of the LWM.
Definition: clock_lwm_registry.cpp:29
Task_registry_multi< Task_id, Task_state > m_executed_registry
Registry of executed tasks.
Definition: clock_lwm_registry.h:133
Time_point_t start_time() const override
Get start time of this clock - the first LWM value (0)
Definition: clock_lwm_registry.cpp:33
std::atomic< Time_point_t > m_current_lwm
Current LWM value.
Definition: clock_lwm_registry.h:135
bool tick(Task_id task_id, Time_point_t) override
Tick performed on the clock when task finishes.
Definition: clock_lwm_registry.cpp:46
bool add_time(Task_id task_id, Time_point_t) override
Registers a task to execute at specific LWM.
Definition: clock_lwm_registry.cpp:37
Interface for clock implementations scheduler uses to schedule tasks.
Definition: scheduler_clock.h:52
uint64_t Time_point_t
Definition: scheduler_clock.h:54
This template class provides a concurrent registry for tasks that handles hash conflicts by allowing ...
Definition: task_registry_multi.h:74
Definition: base_dependency_tracker.h:41
This structure is used to represent a registered task state and update LWM.
Definition: clock_lwm_registry.h:124
bool started
Task has started.
Definition: clock_lwm_registry.h:126
bool finished
Task has finished.
Definition: clock_lwm_registry.h:128
Scheduler_clock instrumentation parameters, packed into this structure to simplify construction of a ...
Definition: scheduler_clock_psi.h:38