1    	// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2    	// vim: ts=8 sw=2 smarttab
3    	
4    	#ifndef CEPH_LIBRBD_IO_IMAGE_DISPATCH_SPEC_H
5    	#define CEPH_LIBRBD_IO_IMAGE_DISPATCH_SPEC_H
6    	
7    	#include "include/int_types.h"
8    	#include "include/buffer.h"
9    	#include "common/zipkin_trace.h"
10   	#include "librbd/io/AioCompletion.h"
11   	#include "librbd/io/Types.h"
12   	#include "librbd/io/ReadResult.h"
13   	#include <boost/variant/variant.hpp>
14   	
15   	namespace librbd {
16   	
17   	class ImageCtx;
18   	
19   	namespace io {
20   	
21   	template <typename ImageCtxT = ImageCtx>
22   	class ImageDispatchSpec {
23   	public:
24   	  struct Read {
25   	    ReadResult read_result;
26   	
27   	    Read(ReadResult &&read_result) : read_result(std::move(read_result)) {
28   	    }
29   	  };
30   	
31   	  struct Discard {
32   	    uint32_t discard_granularity_bytes;
33   	
34   	    Discard(uint32_t discard_granularity_bytes)
35   	      : discard_granularity_bytes(discard_granularity_bytes) {
36   	    }
37   	  };
38   	
39   	  struct Write {
40   	    bufferlist bl;
41   	
42   	    Write(bufferlist&& bl) : bl(std::move(bl)) {
43   	    }
44   	  };
45   	
46   	  struct WriteSame {
47   	    bufferlist bl;
48   	
49   	    WriteSame(bufferlist&& bl) : bl(std::move(bl)) {
50   	    }
51   	  };
52   	
53   	  struct CompareAndWrite {
54   	    bufferlist cmp_bl;
55   	    bufferlist bl;
56   	    uint64_t *mismatch_offset;
57   	
58   	    CompareAndWrite(bufferlist&& cmp_bl, bufferlist&& bl,
59   	                    uint64_t *mismatch_offset)
60   	      : cmp_bl(std::move(cmp_bl)), bl(std::move(bl)),
61   	        mismatch_offset(mismatch_offset) {
62   	    }
63   	  };
64   	
65   	  struct Flush {
66   	    FlushSource flush_source;
67   	
68   	    Flush(FlushSource flush_source) : flush_source(flush_source) {
69   	    }
70   	  };
71   	
72   	  static ImageDispatchSpec* create_read_request(
73   	      ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents,
74   	      ReadResult &&read_result, int op_flags,
75   	      const ZTracer::Trace &parent_trace) {
76   	    return new ImageDispatchSpec(image_ctx, aio_comp,
77   	                                 std::move(image_extents),
78   	                                 Read{std::move(read_result)},
79   	                                 op_flags, parent_trace);
80   	  }
81   	
82   	  static ImageDispatchSpec* create_discard_request(
83   	      ImageCtxT &image_ctx, AioCompletion *aio_comp, uint64_t off, uint64_t len,
84   	      uint32_t discard_granularity_bytes, const ZTracer::Trace &parent_trace) {
85   	    return new ImageDispatchSpec(image_ctx, aio_comp, {{off, len}},
86   	                                 Discard{discard_granularity_bytes},
87   	                                 0, parent_trace);
88   	  }
89   	
90   	  static ImageDispatchSpec* create_write_request(
91   	      ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents,
92   	      bufferlist &&bl, int op_flags, const ZTracer::Trace &parent_trace) {
93   	    return new ImageDispatchSpec(image_ctx, aio_comp, std::move(image_extents),
94   	                                 Write{std::move(bl)}, op_flags, parent_trace);
95   	  }
96   	
97   	  static ImageDispatchSpec* create_write_same_request(
98   	      ImageCtxT &image_ctx, AioCompletion *aio_comp, uint64_t off, uint64_t len,
99   	      bufferlist &&bl, int op_flags, const ZTracer::Trace &parent_trace) {
100  	    return new ImageDispatchSpec(image_ctx, aio_comp, {{off, len}},
101  	                                 WriteSame{std::move(bl)}, op_flags,
102  	                                 parent_trace);
103  	  }
104  	
105  	  static ImageDispatchSpec* create_compare_and_write_request(
106  	      ImageCtxT &image_ctx, AioCompletion *aio_comp, Extents &&image_extents,
107  	      bufferlist &&cmp_bl, bufferlist &&bl, uint64_t *mismatch_offset,
108  	      int op_flags, const ZTracer::Trace &parent_trace) {
109  	    return new ImageDispatchSpec(image_ctx, aio_comp,
110  	                                 std::move(image_extents),
111  	                                 CompareAndWrite{std::move(cmp_bl),
112  	                                                 std::move(bl),
113  	                                                 mismatch_offset},
114  	                                 op_flags, parent_trace);
115  	  }
116  	
117  	  static ImageDispatchSpec* create_flush_request(
118  	      ImageCtxT &image_ctx, AioCompletion *aio_comp,
119  	      FlushSource flush_source, const ZTracer::Trace &parent_trace) {
120  	    return new ImageDispatchSpec(image_ctx, aio_comp, {}, Flush{flush_source},
121  	                                 0, parent_trace);
122  	  }
123  	
(1) Event exn_spec_violation: An exception of type "_ZN5boost16exception_detail10clone_implINS0_19error_info_injectorINSt8ios_base7failureB5cxx11EEEEE" is thrown but the throw list "throw()" doesn't allow it to be thrown. This will cause a call to unexpected() which usually calls terminate().
Also see events: [fun_call_w_exception]
124  	  ~ImageDispatchSpec() {
(2) Event fun_call_w_exception: Called function throws an exception of type "_ZN5boost16exception_detail10clone_implINS0_19error_info_injectorINSt8ios_base7failureB5cxx11EEEEE". [details]
Also see events: [exn_spec_violation]
125  	    m_aio_comp->put();
126  	  }
127  	
128  	  void send();
129  	  void fail(int r);
130  	
131  	  bool is_write_op() const;
132  	
133  	  void start_op();
134  	
135  	  bool tokens_requested(uint64_t flag, uint64_t *tokens);
136  	
137  	  bool was_throttled(uint64_t flag) {
138  	    return m_throttled_flag & flag;
139  	  }
140  	
141  	  void set_throttled(uint64_t flag) {
142  	    m_throttled_flag |= flag;
143  	  }
144  	
145  	  bool were_all_throttled() {
146  	    return (m_throttled_flag & RBD_QOS_MASK) == RBD_QOS_MASK;
147  	  }
148  	
149  	private:
150  	  typedef boost::variant<Read,
151  	                         Discard,
152  	                         Write,
153  	                         WriteSame,
154  	                         CompareAndWrite,
155  	                         Flush> Request;
156  	
157  	  struct SendVisitor;
158  	  struct IsWriteOpVisitor;
159  	  struct TokenRequestedVisitor;
160  	
161  	  ImageDispatchSpec(ImageCtxT& image_ctx, AioCompletion* aio_comp,
162  	                     Extents&& image_extents, Request&& request,
163  	                     int op_flags, const ZTracer::Trace& parent_trace)
164  	    : m_image_ctx(image_ctx), m_aio_comp(aio_comp),
165  	      m_image_extents(std::move(image_extents)), m_request(std::move(request)),
166  	      m_op_flags(op_flags), m_parent_trace(parent_trace) {
167  	    m_aio_comp->get();
168  	  }
169  	
170  	  ImageCtxT& m_image_ctx;
171  	  AioCompletion* m_aio_comp;
172  	  Extents m_image_extents;
173  	  Request m_request;
174  	  int m_op_flags;
175  	  ZTracer::Trace m_parent_trace;
176  	  std::atomic<uint64_t> m_throttled_flag = 0;
177  	
178  	  uint64_t extents_length();
179  	};
180  	
181  	} // namespace io
182  	} // namespace librbd
183  	
184  	extern template class librbd::io::ImageDispatchSpec<librbd::ImageCtx>;
185  	
186  	#endif // CEPH_LIBRBD_IO_IMAGE_DISPATCH_SPEC_H
187