summaryrefslogtreecommitdiffstats
path: root/src/rbd_replay/Replayer.hpp
blob: ddbd05743f1b108e4a470e543bb4af534c2c8d34 (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
// -*- 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) 2014 Adam Crume <adamcrume@gmail.com>
 *
 * 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 _INCLUDED_RBD_REPLAY_REPLAYER_HPP
#define _INCLUDED_RBD_REPLAY_REPLAYER_HPP

#include <chrono>
#include <mutex>
#include <thread>
#include <condition_variable>
#include "rbd_replay/ActionTypes.h"
#include "BoundedBuffer.hpp"
#include "ImageNameMap.hpp"
#include "PendingIO.hpp"

namespace rbd_replay {

class Replayer;

/**
   Performs Actions within a single thread.
 */
class Worker : public ActionCtx {
public:
  explicit Worker(Replayer &replayer);

  void start();

  /// Should only be called by StopThreadAction
  void stop() override;

  void join();

  void send(Action::ptr action);

  void add_pending(PendingIO::ptr io) override;

  void remove_pending(PendingIO::ptr io) override;

  librbd::Image* get_image(imagectx_id_t imagectx_id) override;

  void put_image(imagectx_id_t imagectx_id, librbd::Image* image) override;

  void erase_image(imagectx_id_t imagectx_id) override;

  librbd::RBD* rbd() override;

  librados::IoCtx* ioctx() override;

  void set_action_complete(action_id_t id) override;

  bool readonly() const override;

  rbd_loc map_image_name(std::string image_name, std::string snap_name) const override;

private:
  void run();

  Replayer &m_replayer;
  BoundedBuffer<Action::ptr> m_buffer;
  std::shared_ptr<std::thread> m_thread;
  std::map<action_id_t, PendingIO::ptr> m_pending_ios;
  std::mutex m_pending_ios_mutex;
  std::condition_variable_any m_pending_ios_empty;
  bool m_done;
};


class Replayer {
public:
  explicit Replayer(int num_action_trackers);

  ~Replayer();

  void run(const std::string &replay_file);

  librbd::RBD* get_rbd() {
    return m_rbd;
  }

  librados::IoCtx* get_ioctx() {
    return m_ioctx;
  }

  librbd::Image* get_image(imagectx_id_t imagectx_id);

  void put_image(imagectx_id_t imagectx_id, librbd::Image *image);

  void erase_image(imagectx_id_t imagectx_id);

  void set_action_complete(action_id_t id);

  bool is_action_complete(action_id_t id);

  void wait_for_actions(const action::Dependencies &deps);

  std::string pool_name() const;

  void set_pool_name(std::string pool_name);

  void set_latency_multiplier(float f);

  bool readonly() const;

  void set_readonly(bool readonly);

  void set_image_name_map(const ImageNameMap &map) {
    m_image_name_map = map;
  }

  void set_dump_perf_counters(bool dump_perf_counters) {
    m_dump_perf_counters = dump_perf_counters;
  }

  const ImageNameMap &image_name_map() const {
    return m_image_name_map;
  }

private:
  struct action_tracker_d {
    /// Maps an action ID to the time the action completed
    std::map<action_id_t, std::chrono::system_clock::time_point> actions;
    std::shared_mutex mutex;
    std::condition_variable_any condition;
  };

  void clear_images();

  action_tracker_d &tracker_for(action_id_t id);

  /// Disallow copying
  Replayer(const Replayer& rhs);
  /// Disallow assignment
  const Replayer& operator=(const Replayer& rhs);

  librbd::RBD* m_rbd;
  librados::IoCtx* m_ioctx;
  std::string m_pool_name;
  float m_latency_multiplier;
  bool m_readonly;
  ImageNameMap m_image_name_map;
  bool m_dump_perf_counters;

  std::map<imagectx_id_t, librbd::Image*> m_images;
  std::shared_mutex m_images_mutex;

  /// Actions are hashed across the trackers by ID.
  /// Number of trackers should probably be larger than the number of cores and prime.
  /// Should definitely be odd.
  const int m_num_action_trackers;
  action_tracker_d* m_action_trackers;
};

}

#endif