]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2012 Red Hat | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
14 | ||
15 | ||
16 | #ifndef MDS_CONTEXT_H | |
17 | #define MDS_CONTEXT_H | |
18 | ||
19 | #include "include/Context.h" | |
91327a77 AA |
20 | #include "include/elist.h" |
21 | #include "common/ceph_time.h" | |
22 | #include "common/simple_spin.h" | |
7c673cae FG |
23 | |
24 | class MDSRank; | |
25 | ||
26 | ||
27 | /** | |
28 | * Completion which has access to a reference to the global MDS instance. | |
29 | * | |
30 | * This class exists so that Context subclasses can provide the MDS pointer | |
31 | * from a pointer they already had, e.g. MDCache or Locker, rather than | |
32 | * necessarily having to carry around an extra MDS* pointer. | |
33 | */ | |
34 | class MDSContext : public Context | |
35 | { | |
36 | protected: | |
37 | virtual MDSRank *get_mds() = 0; | |
38 | }; | |
39 | ||
40 | ||
41 | /** | |
42 | * A context which must be called with the big MDS lock held. Subclass | |
43 | * this with a get_mds implementation. | |
44 | */ | |
45 | class MDSInternalContextBase : public MDSContext | |
46 | { | |
47 | public: | |
48 | void complete(int r) override; | |
49 | }; | |
50 | ||
51 | /** | |
52 | * General purpose, lets you pass in an MDS pointer. | |
53 | */ | |
54 | class MDSInternalContext : public MDSInternalContextBase | |
55 | { | |
56 | protected: | |
57 | MDSRank *mds; | |
58 | MDSRank* get_mds() override; | |
59 | ||
60 | public: | |
61 | explicit MDSInternalContext(MDSRank *mds_) : mds(mds_) { | |
62 | assert(mds != NULL); | |
63 | } | |
64 | }; | |
65 | ||
66 | /** | |
67 | * Wrap a regular Context up as an Internal context. Useful | |
68 | * if you're trying to work with one of our more generic frameworks. | |
69 | */ | |
70 | class MDSInternalContextWrapper : public MDSInternalContextBase | |
71 | { | |
72 | protected: | |
73 | MDSRank *mds; | |
74 | Context *fin; | |
75 | MDSRank *get_mds() override; | |
91327a77 | 76 | void finish(int r) override; |
7c673cae FG |
77 | public: |
78 | MDSInternalContextWrapper(MDSRank *m, Context *c) : mds(m), fin(c) {} | |
7c673cae FG |
79 | }; |
80 | ||
81 | class MDSIOContextBase : public MDSContext | |
82 | { | |
83 | public: | |
91327a77 AA |
84 | MDSIOContextBase(bool track=true); |
85 | virtual ~MDSIOContextBase(); | |
86 | MDSIOContextBase(const MDSIOContextBase&) = delete; | |
87 | MDSIOContextBase& operator=(const MDSIOContextBase&) = delete; | |
88 | ||
7c673cae | 89 | void complete(int r) override; |
91327a77 AA |
90 | |
91 | virtual void print(ostream& out) const = 0; | |
92 | ||
93 | static bool check_ios_in_flight(ceph::coarse_mono_time cutoff, | |
94 | std::string& slow_count, | |
95 | ceph::coarse_mono_time& oldest); | |
96 | private: | |
97 | ceph::coarse_mono_time created_at; | |
98 | elist<MDSIOContextBase*>::item list_item; | |
99 | ||
100 | static elist<MDSIOContextBase*> ctx_list; | |
101 | static std::atomic_flag ctx_list_lock; | |
7c673cae FG |
102 | }; |
103 | ||
104 | /** | |
105 | * Completion for an log operation, takes big MDSRank lock | |
106 | * before executing finish function. Update log's safe pos | |
107 | * after finish functuon return. | |
108 | */ | |
109 | class MDSLogContextBase : public MDSIOContextBase | |
110 | { | |
111 | protected: | |
112 | uint64_t write_pos; | |
113 | public: | |
114 | MDSLogContextBase() : write_pos(0) {} | |
115 | void complete(int r) final; | |
116 | void set_write_pos(uint64_t wp) { write_pos = wp; } | |
117 | virtual void pre_finish(int r) {} | |
91327a77 AA |
118 | void print(ostream& out) const override { |
119 | out << "log_event(" << write_pos << ")"; | |
120 | } | |
7c673cae FG |
121 | }; |
122 | ||
123 | /** | |
124 | * Completion for an I/O operation, takes big MDSRank lock | |
125 | * before executing finish function. | |
126 | */ | |
127 | class MDSIOContext : public MDSIOContextBase | |
128 | { | |
129 | protected: | |
130 | MDSRank *mds; | |
131 | MDSRank* get_mds() override; | |
132 | ||
133 | public: | |
134 | explicit MDSIOContext(MDSRank *mds_) : mds(mds_) { | |
135 | assert(mds != NULL); | |
136 | } | |
137 | }; | |
138 | ||
139 | /** | |
140 | * Wrap a regular Context up as an IO Context. Useful | |
141 | * if you're trying to work with one of our more generic frameworks. | |
142 | */ | |
143 | class MDSIOContextWrapper : public MDSIOContextBase | |
144 | { | |
145 | protected: | |
146 | MDSRank *mds; | |
147 | Context *fin; | |
148 | MDSRank *get_mds() override; | |
149 | public: | |
150 | MDSIOContextWrapper(MDSRank *m, Context *c) : mds(m), fin(c) {} | |
151 | void finish(int r) override; | |
91327a77 AA |
152 | void print(ostream& out) const override { |
153 | out << "io_context_wrapper(" << fin << ")"; | |
154 | } | |
7c673cae FG |
155 | }; |
156 | ||
157 | /** | |
158 | * No-op for callers expecting MDSInternalContextBase | |
159 | */ | |
160 | class C_MDSInternalNoop final : public MDSInternalContextBase | |
161 | { | |
162 | MDSRank* get_mds() override {ceph_abort();} | |
163 | public: | |
164 | void finish(int r) override {} | |
165 | void complete(int r) override { delete this; } | |
166 | }; | |
167 | ||
168 | ||
169 | /** | |
170 | * This class is used where you have an MDSInternalContextBase but | |
171 | * you sometimes want to call it back from an I/O completion. | |
172 | */ | |
173 | class C_IO_Wrapper : public MDSIOContext | |
174 | { | |
175 | protected: | |
176 | bool async; | |
177 | MDSInternalContextBase *wrapped; | |
178 | void finish(int r) override { | |
179 | wrapped->complete(r); | |
180 | wrapped = nullptr; | |
181 | } | |
182 | public: | |
183 | C_IO_Wrapper(MDSRank *mds_, MDSInternalContextBase *wrapped_) : | |
184 | MDSIOContext(mds_), async(true), wrapped(wrapped_) { | |
185 | assert(wrapped != NULL); | |
186 | } | |
187 | ||
188 | ~C_IO_Wrapper() override { | |
189 | if (wrapped != nullptr) { | |
190 | delete wrapped; | |
191 | wrapped = nullptr; | |
192 | } | |
193 | } | |
194 | void complete(int r) final; | |
91327a77 AA |
195 | void print(ostream& out) const override { |
196 | out << "io_wrapper(" << wrapped << ")"; | |
197 | } | |
7c673cae FG |
198 | }; |
199 | ||
200 | ||
201 | /** | |
202 | * Gather needs a default-constructable class | |
203 | */ | |
204 | class MDSInternalContextGather : public MDSInternalContextBase | |
205 | { | |
206 | protected: | |
207 | MDSRank *get_mds() override; | |
208 | }; | |
209 | ||
210 | ||
211 | class MDSGather : public C_GatherBase<MDSInternalContextBase, MDSInternalContextGather> | |
212 | { | |
213 | public: | |
214 | MDSGather(CephContext *cct, MDSInternalContextBase *onfinish) : C_GatherBase<MDSInternalContextBase, MDSInternalContextGather>(cct, onfinish) {} | |
215 | protected: | |
216 | MDSRank *get_mds() override {return NULL;} | |
217 | }; | |
218 | ||
219 | ||
220 | typedef C_GatherBuilderBase<MDSInternalContextBase, MDSGather> MDSGatherBuilder; | |
221 | ||
222 | #endif // MDS_CONTEXT_H |