return m_replayer.get_ioctx();
}
-
void Worker::set_action_complete(action_id_t id) {
m_replayer.set_action_complete(id);
}
+bool Worker::readonly() const {
+ return m_replayer.readonly();
+}
+
Replayer::Replayer(int num_action_trackers)
: m_num_action_trackers(num_action_trackers),
void Replayer::set_latency_multiplier(float f) {
m_latency_multiplier = f;
}
+
+bool Replayer::readonly() const {
+ return m_readonly;
+}
+
+void Replayer::set_readonly(bool readonly) {
+ m_readonly = readonly;
+}
void set_action_complete(action_id_t id);
+ bool readonly() const;
+
private:
void run();
void set_latency_multiplier(float f);
+ bool readonly() const;
+
+ void set_readonly(bool readonly);
+
private:
struct action_tracker_d {
// Maps an action ID to the time the action completed
librbd::RBD* m_rbd;
librados::IoCtx* m_ioctx;
float m_latency_multiplier;
+ bool m_readonly;
std::map<imagectx_id_t, librbd::Image*> m_images;
boost::shared_mutex m_images_mutex;
PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
io->bufferlist().append_zero(m_length);
worker.add_pending(io);
- int r = image->aio_write(m_offset, m_length, io->bufferlist(), &io->completion());
- assertf(r >= 0, "id = %d, r = %d", id(), r);
+ if (worker.readonly()) {
+ worker.remove_pending(io);
+ } else {
+ int r = image->aio_write(m_offset, m_length, io->bufferlist(), &io->completion());
+ assertf(r >= 0, "id = %d, r = %d", id(), r);
+ }
}
std::ostream& AioWriteAction::dump(std::ostream& o) const {
PendingIO::ptr io(new PendingIO(pending_io_id(), worker));
worker.add_pending(io);
io->bufferlist().append_zero(m_length);
- ssize_t r = image->write(m_offset, m_length, io->bufferlist());
- assertf(r >= 0, "id = %d, r = %d", id(), r);
+ if (!worker.readonly()) {
+ ssize_t r = image->write(m_offset, m_length, io->bufferlist());
+ assertf(r >= 0, "id = %d, r = %d", id(), r);
+ }
worker.remove_pending(io);
}
librbd::Image *image = new librbd::Image();
librbd::RBD *rbd = worker.rbd();
int r;
- if (m_readonly) {
+ if (m_readonly || worker.readonly()) {
r = rbd->open_read_only(*worker.ioctx(), *image, m_name.c_str(), m_snap_name.c_str());
} else {
r = rbd->open(*worker.ioctx(), *image, m_name.c_str(), m_snap_name.c_str());
virtual void add_pending(boost::shared_ptr<PendingIO> io) = 0;
+ virtual bool readonly() const = 0;
+
virtual void remove_pending(boost::shared_ptr<PendingIO> io) = 0;
virtual void set_action_complete(action_id_t id) = 0;
ios = []
pendingIOs = {}
limit = 100000000000
- ignoreWrites = True
printOnRead = False
printOnWrite = False
threads = {}
if printOnRead:
print str(thread.pendingIO)
elif event.name == "librbd:write_enter":
- if not ignoreWrites:
- name = event["name"]
- readid = event["id"]
- offset = event["off"]
- length = event["buf_len"]
- imagectx = event["imagectx"]
- ionum = self.nextID()
- thread.pendingIO = WriteIO(ionum, ts, thread, thread.pendingIO, imagectx, [Extent(offset, length)])
- thread.pendingIO.addThreadCompletionDependencies(threads, self.recentCompletions)
- thread.issuedIO(thread.pendingIO)
- ios.append(thread.pendingIO)
+ name = event["name"]
+ readid = event["id"]
+ offset = event["off"]
+ length = event["buf_len"]
+ imagectx = event["imagectx"]
+ ionum = self.nextID()
+ thread.pendingIO = WriteIO(ionum, ts, thread, thread.pendingIO, imagectx, [Extent(offset, length)])
+ thread.pendingIO.addThreadCompletionDependencies(threads, self.recentCompletions)
+ thread.issuedIO(thread.pendingIO)
+ ios.append(thread.pendingIO)
elif event.name == "librbd:write_exit":
- if not ignoreWrites:
- thread.pendingIO.end_time = ts
- completionIO = CompletionIO(ts, thread, thread.pendingIO)
- thread.completedIO(completionIO)
- ios.append(completionIO)
- completed(completionIO)
- if printOnRead:
- print str(thread.pendingIO)
+ thread.pendingIO.end_time = ts
+ completionIO = CompletionIO(ts, thread, thread.pendingIO)
+ thread.completedIO(completionIO)
+ ios.append(completionIO)
+ completed(completionIO)
+ if printOnRead:
+ print str(thread.pendingIO)
elif event.name == "librbd:aio_read_enter":
name = event["name"]
readid = event["id"]
if printOnRead:
print str(thread.pendingIO)
elif event.name == "librbd:aio_write_enter":
- if not ignoreWrites:
- name = event["name"]
- writeid = event["id"]
- offset = event["off"]
- length = event["len"]
- completion = event["completion"]
- imagectx = event["imagectx"]
- ionum = self.nextID()
- thread.pendingIO = AioWriteIO(ionum, ts, thread, thread.pendingIO, imagectx, [Extent(offset, length)])
- thread.pendingIO.addThreadCompletionDependencies(threads, self.recentCompletions)
- thread.issuedIO(thread.pendingIO)
- ios.append(thread.pendingIO)
- pendingIOs[completion] = thread.pendingIO
- if printOnRead:
- print str(thread.pendingIO)
+ name = event["name"]
+ writeid = event["id"]
+ offset = event["off"]
+ length = event["len"]
+ completion = event["completion"]
+ imagectx = event["imagectx"]
+ ionum = self.nextID()
+ thread.pendingIO = AioWriteIO(ionum, ts, thread, thread.pendingIO, imagectx, [Extent(offset, length)])
+ thread.pendingIO.addThreadCompletionDependencies(threads, self.recentCompletions)
+ thread.issuedIO(thread.pendingIO)
+ ios.append(thread.pendingIO)
+ pendingIOs[completion] = thread.pendingIO
+ if printOnRead:
+ print str(thread.pendingIO)
elif event.name == "librbd:aio_complete_enter":
completion = event["completion"]
retval = event["rval"]
static void usage(const char* program) {
cout << "Usage: " << program << " --conf=<config_file> <replay_file>" << std::endl;
- cout << "Options:" << endl;
- cout << " --latency-multiplier <float> Multiplies inter-request latencies. Default: 1" << endl;
+ cout << "Options:" << std::endl;
+ cout << " --latency-multiplier <float> Multiplies inter-request latencies. Default: 1" << std::endl;
+ cout << " --read-only Only perform non-destructive operations." << std::endl;
}
int main(int argc, const char **argv) {
std::vector<const char*>::iterator i;
float latency_multiplier = 1;
+ bool readonly = false;
std::string val;
std::ostringstream err;
for (i = args.begin(); i != args.end(); ) {
cerr << err.str() << std::endl;
return 1;
}
+ } else if (ceph_argparse_flag(args, i, "--read-only", (char*)NULL)) {
+ readonly = true;
} else if (ceph_argparse_flag(args, i, "-h", "--help", (char*)NULL)) {
usage(argv[0]);
return 0;
unsigned int nthreads = boost::thread::hardware_concurrency();
Replayer replayer(2 * nthreads + 1);
replayer.set_latency_multiplier(latency_multiplier);
+ replayer.set_readonly(readonly);
replayer.run(replay_file);
}