summaryrefslogtreecommitdiff
path: root/src/tools/rbd_mirror/InstanceReplayer.h
blob: 2bd8d11f59d51aaffbad51f4dfa4029074558e2b (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
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#ifndef RBD_MIRROR_INSTANCE_REPLAYER_H
#define RBD_MIRROR_INSTANCE_REPLAYER_H

#include <map>
#include <sstream>

#include "common/AsyncOpTracker.h"
#include "common/Formatter.h"
#include "common/ceph_mutex.h"
#include "tools/rbd_mirror/Types.h"

namespace journal { struct CacheManagerHandler; }

namespace librbd { class ImageCtx; }

namespace rbd {
namespace mirror {

template <typename> class ImageReplayer;
template <typename> class InstanceWatcher;
template <typename> class MirrorStatusUpdater;
template <typename> class ServiceDaemon;
template <typename> struct Threads;

template <typename ImageCtxT = librbd::ImageCtx>
class InstanceReplayer {
public:
  static InstanceReplayer* create(
      librados::IoCtx &local_io_ctx, const std::string &local_mirror_uuid,
      Threads<ImageCtxT> *threads, ServiceDaemon<ImageCtxT> *service_daemon,
      MirrorStatusUpdater<ImageCtxT>* local_status_updater,
      journal::CacheManagerHandler *cache_manager_handler) {
    return new InstanceReplayer(local_io_ctx, local_mirror_uuid, threads,
                                service_daemon, local_status_updater,
                                cache_manager_handler);
  }
  void destroy() {
    delete this;
  }

  InstanceReplayer(librados::IoCtx &local_io_ctx,
                   const std::string &local_mirror_uuid,
                   Threads<ImageCtxT> *threads,
                   ServiceDaemon<ImageCtxT> *service_daemon,
                   MirrorStatusUpdater<ImageCtxT>* local_status_updater,
                   journal::CacheManagerHandler *cache_manager_handler);
  ~InstanceReplayer();

  int init();
  void shut_down();

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

  void add_peer(const Peer<ImageCtxT>& peer);

  void acquire_image(InstanceWatcher<ImageCtxT> *instance_watcher,
                     const std::string &global_image_id, Context *on_finish);
  void release_image(const std::string &global_image_id, Context *on_finish);
  void remove_peer_image(const std::string &global_image_id,
                         const std::string &peer_mirror_uuid,
                         Context *on_finish);

  void release_all(Context *on_finish);

  void print_status(Formatter *f);
  void start();
  void stop();
  void restart();
  void flush();

  void stop(Context *on_finish);

private:
  /**
   * @verbatim
   *
   * <uninitialized> <-------------------\
   *    | (init)                         |                    (repeat for each
   *    v                             STOP_IMAGE_REPLAYER ---\ image replayer)
   * SCHEDULE_IMAGE_STATE_CHECK_TASK     ^         ^         |
   *    |                                |         |         |
   *    v          (shut_down)           |         \---------/
   * <initialized> -----------------> WAIT_FOR_OPS
   *
   * @endverbatim
   */

  typedef std::set<Peer<ImageCtxT>> Peers;

  librados::IoCtx &m_local_io_ctx;
  std::string m_local_mirror_uuid;
  Threads<ImageCtxT> *m_threads;
  ServiceDaemon<ImageCtxT> *m_service_daemon;
  MirrorStatusUpdater<ImageCtxT>* m_local_status_updater;
  journal::CacheManagerHandler *m_cache_manager_handler;

  ceph::mutex m_lock;
  AsyncOpTracker m_async_op_tracker;
  std::map<std::string, ImageReplayer<ImageCtxT> *> m_image_replayers;
  Peers m_peers;
  Context *m_image_state_check_task = nullptr;
  Context *m_on_shut_down = nullptr;
  bool m_manual_stop = false;

  void wait_for_ops();
  void handle_wait_for_ops(int r);

  void start_image_replayer(ImageReplayer<ImageCtxT> *image_replayer);
  void queue_start_image_replayers();
  void start_image_replayers(int r);

  void stop_image_replayer(ImageReplayer<ImageCtxT> *image_replayer,
                           Context *on_finish);

  void stop_image_replayers();
  void handle_stop_image_replayers(int r);

  void schedule_image_state_check_task();
  void cancel_image_state_check_task();
};

} // namespace mirror
} // namespace rbd

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

#endif // RBD_MIRROR_INSTANCE_REPLAYER_H