summaryrefslogtreecommitdiffstats
path: root/src/tools/rbd_mirror/PoolWatcher.h
blob: 2905de15fba24c224dcd2d80f4df22cbb2654f1a (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#ifndef CEPH_RBD_MIRROR_POOL_WATCHER_H
#define CEPH_RBD_MIRROR_POOL_WATCHER_H

#include <map>
#include <memory>
#include <set>
#include <string>

#include "common/AsyncOpTracker.h"
#include "common/ceph_context.h"
#include "common/ceph_mutex.h"
#include "include/rados/librados.hpp"
#include "tools/rbd_mirror/Types.h"
#include <boost/functional/hash.hpp>
#include <boost/optional.hpp>
#include "include/ceph_assert.h"
#include "tools/rbd_mirror/pool_watcher/Types.h"

namespace librbd { struct ImageCtx; }

namespace rbd {
namespace mirror {

template <typename> struct Threads;

/**
 * Keeps track of images that have mirroring enabled within all
 * pools.
 */
template <typename ImageCtxT = librbd::ImageCtx>
class PoolWatcher {
public:
  static PoolWatcher* create(Threads<ImageCtxT> *threads,
                             librados::IoCtx &io_ctx,
                             const std::string& mirror_uuid,
                             pool_watcher::Listener &listener) {
    return new PoolWatcher(threads, io_ctx, mirror_uuid, listener);
  }

  PoolWatcher(Threads<ImageCtxT> *threads,
              librados::IoCtx &io_ctx,
              const std::string& mirror_uuid,
              pool_watcher::Listener &listener);
  ~PoolWatcher();
  PoolWatcher(const PoolWatcher&) = delete;
  PoolWatcher& operator=(const PoolWatcher&) = delete;

  bool is_blocklisted() const;

  void init(Context *on_finish = nullptr);
  void shut_down(Context *on_finish);

  inline uint64_t get_image_count() const {
    std::lock_guard locker{m_lock};
    return m_image_ids.size();
  }

private:
  /**
   * @verbatim
   *
   * <start>
   *    |
   *    v
   *  INIT
   *    |
   *    v
   * REGISTER_WATCHER
   *    |
   *    |/--------------------------------\
   *    |                                 |
   *    v                                 |
   * REFRESH_IMAGES                       |
   *    |                                 |
   *    |/----------------------------\   |
   *    |                             |   |
   *    v                             |   |
   * NOTIFY_LISTENER                  |   |
   *    |                             |   |
   *    v                             |   |
   *  IDLE ---\                       |   |
   *    |     |                       |   |
   *    |     |\---> IMAGE_UPDATED    |   |
   *    |     |         |             |   |
   *    |     |         v             |   |
   *    |     |      GET_IMAGE_NAME --/   |
   *    |     |                           |
   *    |     \----> WATCH_ERROR ---------/
   *    v
   * SHUT_DOWN
   *    |
   *    v
   * UNREGISTER_WATCHER
   *    |
   *    v
   * <finish>
   *
   * @endverbatim
   */
  class MirroringWatcher;

  Threads<ImageCtxT> *m_threads;
  librados::IoCtx m_io_ctx;
  std::string m_mirror_uuid;
  pool_watcher::Listener &m_listener;

  ImageIds m_refresh_image_ids;
  bufferlist m_out_bl;

  mutable ceph::mutex m_lock;

  Context *m_on_init_finish = nullptr;

  ImageIds m_image_ids;

  bool m_pending_updates = false;
  bool m_notify_listener_in_progress = false;
  ImageIds m_pending_image_ids;
  ImageIds m_pending_added_image_ids;
  ImageIds m_pending_removed_image_ids;

  MirroringWatcher *m_mirroring_watcher;

  Context *m_timer_ctx = nullptr;

  AsyncOpTracker m_async_op_tracker;
  bool m_blocklisted = false;
  bool m_shutting_down = false;
  bool m_image_ids_invalid = true;
  bool m_refresh_in_progress = false;
  bool m_deferred_refresh = false;

  void register_watcher();
  void handle_register_watcher(int r);
  void unregister_watcher();

  void refresh_images();
  void handle_refresh_images(int r);

  void schedule_refresh_images(double interval);
  void process_refresh_images();

  void handle_rewatch_complete(int r);
  void handle_image_updated(const std::string &image_id,
                            const std::string &global_image_id,
                            bool enabled);

  void schedule_listener();
  void notify_listener();

};

} // namespace mirror
} // namespace rbd

extern template class rbd::mirror::PoolWatcher<librbd::ImageCtx>;

#endif // CEPH_RBD_MIRROR_POOL_WATCHER_H