summaryrefslogtreecommitdiffstats
path: root/src/tools/rbd_mirror/ImageDeleter.h
blob: 5fe79496bc998797c039262c86f7ad76801f5e82 (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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2016 SUSE LINUX GmbH
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#ifndef CEPH_RBD_MIRROR_IMAGE_DELETER_H
#define CEPH_RBD_MIRROR_IMAGE_DELETER_H

#include "include/utime.h"
#include "common/AsyncOpTracker.h"
#include "common/ceph_mutex.h"
#include "common/Timer.h"
#include "tools/rbd_mirror/Types.h"
#include "tools/rbd_mirror/image_deleter/Types.h"
#include <atomic>
#include <deque>
#include <iosfwd>
#include <map>
#include <memory>
#include <vector>

class AdminSocketHook;
class Context;
namespace librbd {
struct ImageCtx;
namespace asio { struct ContextWQ; }
} // namespace librbd

namespace rbd {
namespace mirror {

template <typename> class ServiceDaemon;
template <typename> class Threads;
template <typename> class Throttler;

namespace image_deleter { template <typename> struct TrashWatcher; }

/**
 * Manage deletion of non-primary images.
 */
template <typename ImageCtxT = librbd::ImageCtx>
class ImageDeleter {
public:
  static ImageDeleter* create(
      librados::IoCtx& local_io_ctx, Threads<librbd::ImageCtx>* threads,
      Throttler<librbd::ImageCtx>* image_deletion_throttler,
      ServiceDaemon<librbd::ImageCtx>* service_daemon) {
    return new ImageDeleter(local_io_ctx, threads, image_deletion_throttler,
                            service_daemon);
  }

  ImageDeleter(librados::IoCtx& local_io_ctx,
               Threads<librbd::ImageCtx>* threads,
               Throttler<librbd::ImageCtx>* image_deletion_throttler,
               ServiceDaemon<librbd::ImageCtx>* service_daemon);

  ImageDeleter(const ImageDeleter&) = delete;
  ImageDeleter& operator=(const ImageDeleter&) = delete;

  static void trash_move(librados::IoCtx& local_io_ctx,
                         const std::string& global_image_id, bool resync,
                         librbd::asio::ContextWQ* work_queue,
                         Context* on_finish);

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

  void print_status(Formatter *f);

  // for testing purposes
  void wait_for_deletion(const std::string &image_id,
                         bool scheduled_only, Context* on_finish);

  std::vector<std::string> get_delete_queue_items();
  std::vector<std::pair<std::string, int> > get_failed_queue_items();

  inline void set_busy_timer_interval(double interval) {
    m_busy_interval = interval;
  }

private:
  using clock_t = ceph::real_clock;
  struct TrashListener : public image_deleter::TrashListener {
    ImageDeleter *image_deleter;

    TrashListener(ImageDeleter *image_deleter) : image_deleter(image_deleter) {
    }

    void handle_trash_image(const std::string& image_id,
      const ceph::real_clock::time_point& deferment_end_time) override {
      image_deleter->handle_trash_image(image_id, deferment_end_time);
    }
  };

  struct DeleteInfo {
    std::string image_id;

    image_deleter::ErrorResult error_result = {};
    int error_code = 0;
    clock_t::time_point retry_time;
    int retries = 0;

    DeleteInfo(const std::string& image_id)
      : image_id(image_id) {
    }

    inline bool operator==(const DeleteInfo& delete_info) const {
      return (image_id == delete_info.image_id);
    }

    friend std::ostream& operator<<(std::ostream& os, DeleteInfo& delete_info) {
      os << "[image_id=" << delete_info.image_id << "]";
    return os;
    }

    void print_status(Formatter *f,
                      bool print_failure_info=false);
  };
  typedef std::shared_ptr<DeleteInfo> DeleteInfoRef;
  typedef std::deque<DeleteInfoRef> DeleteQueue;
  typedef std::map<std::string, Context*> OnDeleteContexts;

  librados::IoCtx& m_local_io_ctx;
  Threads<librbd::ImageCtx>* m_threads;
  Throttler<librbd::ImageCtx>* m_image_deletion_throttler;
  ServiceDaemon<librbd::ImageCtx>* m_service_daemon;

  image_deleter::TrashWatcher<ImageCtxT>* m_trash_watcher = nullptr;
  TrashListener m_trash_listener;

  std::atomic<unsigned> m_running { 1 };

  double m_busy_interval = 1;

  AsyncOpTracker m_async_op_tracker;

  ceph::mutex m_lock;
  DeleteQueue m_delete_queue;
  DeleteQueue m_retry_delete_queue;
  DeleteQueue m_in_flight_delete_queue;

  OnDeleteContexts m_on_delete_contexts;

  AdminSocketHook *m_asok_hook = nullptr;

  Context *m_timer_ctx = nullptr;

  bool process_image_delete();

  void complete_active_delete(DeleteInfoRef* delete_info, int r);
  void enqueue_failed_delete(DeleteInfoRef* delete_info, int error_code,
                             double retry_delay);

  DeleteInfoRef find_delete_info(const std::string &image_id);

  void remove_images();
  void remove_image(DeleteInfoRef delete_info);
  void handle_remove_image(DeleteInfoRef delete_info, int r);

  void schedule_retry_timer();
  void cancel_retry_timer();
  void handle_retry_timer();

  void handle_trash_image(const std::string& image_id,
                          const clock_t::time_point& deferment_end_time);

  void shut_down_trash_watcher(Context* on_finish);
  void wait_for_ops(Context* on_finish);
  void cancel_all_deletions(Context* on_finish);

  void notify_on_delete(const std::string& image_id, int r);

};

} // namespace mirror
} // namespace rbd

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

#endif // CEPH_RBD_MIRROR_IMAGE_DELETER_H