1/*
2 Copyright (c) 2017, Facebook, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
17#pragma once
18
19/* C++ standard header files */
20#include <atomic>
21#include <signal.h>
22#include <stdlib.h>
23#include <string>
24#include <string.h>
25#include <time.h>
26#include <vector>
27
28/* MySQL header files */
29#include "./my_global.h"
30#include "./my_stacktrace.h"
31
32/* MyRocks header files */
33#include "./rdb_utils.h"
34
35namespace myrocks {
36
37// Rdb_io_watchdog does not support Windows ATM.
38#ifdef HAVE_TIMER_DELETE
39
40class Rdb_io_watchdog {
41 const int RDB_IO_WRITE_BUFFER_SIZE = 4096;
42 const char *const RDB_IO_DUMMY_FILE_NAME = "myrocks_io_watchdog_write_file";
43
44 private:
45 timer_t m_io_check_timer, m_io_check_watchdog_timer;
46 std::atomic<bool> m_io_in_progress;
47 std::vector<std::string> m_dirs_to_check;
48 uint32_t m_write_timeout;
49 mysql_mutex_t m_reset_mutex;
50 char *m_buf;
51
52 int check_write_access(const std::string &dirname) const;
53 void io_check_callback(union sigval timer_data);
54 void expire_io_callback(union sigval timer_data);
55
56 int stop_timers() {
57 int ret = 0;
58
59 if (m_io_check_watchdog_timer) {
60 ret = timer_delete(m_io_check_watchdog_timer);
61
62 if (!ret) {
63 m_io_check_watchdog_timer = nullptr;
64 }
65 }
66
67 if (m_io_check_timer && !ret) {
68 ret = timer_delete(m_io_check_timer);
69
70 if (!ret) {
71 m_io_check_timer = nullptr;
72 }
73 }
74
75 return ret;
76 }
77
78 static void io_check_callback_wrapper(union sigval timer_data) {
79 Rdb_io_watchdog *io_watchdog =
80 static_cast<Rdb_io_watchdog *>(timer_data.sival_ptr);
81 DBUG_ASSERT(io_watchdog != nullptr);
82
83 io_watchdog->io_check_callback(timer_data);
84 }
85
86 static void expire_io_callback_wrapper(union sigval timer_data) {
87 Rdb_io_watchdog *io_watchdog =
88 static_cast<Rdb_io_watchdog *>(timer_data.sival_ptr);
89 DBUG_ASSERT(io_watchdog != nullptr);
90
91 io_watchdog->expire_io_callback(timer_data);
92 }
93
94 public:
95 explicit Rdb_io_watchdog(const std::vector<std::string> &directories)
96 : m_io_check_timer(nullptr), m_io_check_watchdog_timer(nullptr),
97 m_io_in_progress(false), m_dirs_to_check(std::move(directories)),
98 m_buf(nullptr) {
99 DBUG_ASSERT(m_dirs_to_check.size() > 0);
100 mysql_mutex_init(0, &m_reset_mutex, MY_MUTEX_INIT_FAST);
101 }
102
103 ~Rdb_io_watchdog() {
104 // We're shutting down. Ignore errors possibly coming from timer deletion.
105 static_cast<void>(stop_timers());
106 mysql_mutex_destroy(&m_reset_mutex);
107 free(m_buf);
108 }
109
110 int reset_timeout(const uint32_t &write_timeout);
111
112 Rdb_io_watchdog(const Rdb_io_watchdog &) = delete;
113 Rdb_io_watchdog &operator=(const Rdb_io_watchdog &) = delete;
114};
115
116#endif
117} // namespace myrocks
118