]>
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 | ||
11fdf7f2 TL |
19 | #include <vector> |
20 | #include <deque> | |
21 | ||
7c673cae | 22 | #include "include/Context.h" |
91327a77 | 23 | #include "include/elist.h" |
11fdf7f2 | 24 | #include "include/spinlock.h" |
91327a77 | 25 | #include "common/ceph_time.h" |
7c673cae FG |
26 | |
27 | class MDSRank; | |
28 | ||
7c673cae FG |
29 | /** |
30 | * Completion which has access to a reference to the global MDS instance. | |
31 | * | |
32 | * This class exists so that Context subclasses can provide the MDS pointer | |
33 | * from a pointer they already had, e.g. MDCache or Locker, rather than | |
34 | * necessarily having to carry around an extra MDS* pointer. | |
35 | */ | |
36 | class MDSContext : public Context | |
37 | { | |
11fdf7f2 TL |
38 | public: |
39 | template<template<typename> class A> | |
40 | using vec_alloc = std::vector<MDSContext*, A<MDSContext*>>; | |
41 | using vec = vec_alloc<std::allocator>; | |
42 | ||
43 | template<template<typename> class A> | |
44 | using que_alloc = std::deque<MDSContext*, A<MDSContext*>>; | |
45 | using que = que_alloc<std::allocator>; | |
46 | ||
47 | void complete(int r) override; | |
7c673cae FG |
48 | virtual MDSRank *get_mds() = 0; |
49 | }; | |
50 | ||
11fdf7f2 TL |
51 | /* Children of this could have used multiple inheritance with MDSHolder and |
52 | * MDSContext but then get_mds() would be ambiguous. | |
7c673cae | 53 | */ |
11fdf7f2 TL |
54 | template<class T> |
55 | class MDSHolder : public T | |
7c673cae FG |
56 | { |
57 | public: | |
11fdf7f2 TL |
58 | MDSRank* get_mds() override { |
59 | return mds; | |
60 | } | |
61 | ||
62 | protected: | |
63 | MDSHolder() = delete; | |
64 | MDSHolder(MDSRank* mds) : mds(mds) { | |
65 | ceph_assert(mds != nullptr); | |
66 | } | |
67 | ||
68 | MDSRank* mds; | |
7c673cae FG |
69 | }; |
70 | ||
71 | /** | |
72 | * General purpose, lets you pass in an MDS pointer. | |
73 | */ | |
11fdf7f2 | 74 | class MDSInternalContext : public MDSHolder<MDSContext> |
7c673cae | 75 | { |
7c673cae | 76 | public: |
11fdf7f2 TL |
77 | MDSInternalContext() = delete; |
78 | ||
79 | protected: | |
80 | explicit MDSInternalContext(MDSRank *mds_) : MDSHolder(mds_) {} | |
7c673cae FG |
81 | }; |
82 | ||
83 | /** | |
84 | * Wrap a regular Context up as an Internal context. Useful | |
85 | * if you're trying to work with one of our more generic frameworks. | |
86 | */ | |
11fdf7f2 | 87 | class MDSInternalContextWrapper : public MDSInternalContext |
7c673cae FG |
88 | { |
89 | protected: | |
11fdf7f2 | 90 | Context *fin = nullptr; |
91327a77 | 91 | void finish(int r) override; |
7c673cae | 92 | public: |
11fdf7f2 | 93 | MDSInternalContextWrapper(MDSRank *m, Context *c) : MDSInternalContext(m), fin(c) {} |
7c673cae FG |
94 | }; |
95 | ||
96 | class MDSIOContextBase : public MDSContext | |
97 | { | |
98 | public: | |
91327a77 AA |
99 | MDSIOContextBase(bool track=true); |
100 | virtual ~MDSIOContextBase(); | |
101 | MDSIOContextBase(const MDSIOContextBase&) = delete; | |
102 | MDSIOContextBase& operator=(const MDSIOContextBase&) = delete; | |
103 | ||
7c673cae | 104 | void complete(int r) override; |
91327a77 AA |
105 | |
106 | virtual void print(ostream& out) const = 0; | |
107 | ||
108 | static bool check_ios_in_flight(ceph::coarse_mono_time cutoff, | |
109 | std::string& slow_count, | |
110 | ceph::coarse_mono_time& oldest); | |
111 | private: | |
112 | ceph::coarse_mono_time created_at; | |
113 | elist<MDSIOContextBase*>::item list_item; | |
e306af50 TL |
114 | |
115 | friend struct MDSIOContextList; | |
7c673cae FG |
116 | }; |
117 | ||
118 | /** | |
119 | * Completion for an log operation, takes big MDSRank lock | |
120 | * before executing finish function. Update log's safe pos | |
121 | * after finish functuon return. | |
122 | */ | |
123 | class MDSLogContextBase : public MDSIOContextBase | |
124 | { | |
125 | protected: | |
11fdf7f2 | 126 | uint64_t write_pos = 0; |
7c673cae | 127 | public: |
11fdf7f2 | 128 | MDSLogContextBase() = default; |
7c673cae FG |
129 | void complete(int r) final; |
130 | void set_write_pos(uint64_t wp) { write_pos = wp; } | |
131 | virtual void pre_finish(int r) {} | |
91327a77 AA |
132 | void print(ostream& out) const override { |
133 | out << "log_event(" << write_pos << ")"; | |
134 | } | |
7c673cae FG |
135 | }; |
136 | ||
137 | /** | |
138 | * Completion for an I/O operation, takes big MDSRank lock | |
139 | * before executing finish function. | |
140 | */ | |
11fdf7f2 | 141 | class MDSIOContext : public MDSHolder<MDSIOContextBase> |
7c673cae | 142 | { |
7c673cae | 143 | public: |
11fdf7f2 | 144 | explicit MDSIOContext(MDSRank *mds_) : MDSHolder(mds_) {} |
7c673cae FG |
145 | }; |
146 | ||
147 | /** | |
148 | * Wrap a regular Context up as an IO Context. Useful | |
149 | * if you're trying to work with one of our more generic frameworks. | |
150 | */ | |
11fdf7f2 | 151 | class MDSIOContextWrapper : public MDSHolder<MDSIOContextBase> |
7c673cae FG |
152 | { |
153 | protected: | |
7c673cae | 154 | Context *fin; |
7c673cae | 155 | public: |
11fdf7f2 | 156 | MDSIOContextWrapper(MDSRank *m, Context *c) : MDSHolder(m), fin(c) {} |
7c673cae | 157 | void finish(int r) override; |
91327a77 AA |
158 | void print(ostream& out) const override { |
159 | out << "io_context_wrapper(" << fin << ")"; | |
160 | } | |
7c673cae FG |
161 | }; |
162 | ||
163 | /** | |
11fdf7f2 | 164 | * No-op for callers expecting MDSInternalContext |
7c673cae | 165 | */ |
11fdf7f2 | 166 | class C_MDSInternalNoop : public MDSContext |
7c673cae | 167 | { |
7c673cae FG |
168 | public: |
169 | void finish(int r) override {} | |
170 | void complete(int r) override { delete this; } | |
11fdf7f2 TL |
171 | protected: |
172 | MDSRank* get_mds() override final {ceph_abort();} | |
7c673cae FG |
173 | }; |
174 | ||
175 | ||
176 | /** | |
11fdf7f2 | 177 | * This class is used where you have an MDSInternalContext but |
7c673cae FG |
178 | * you sometimes want to call it back from an I/O completion. |
179 | */ | |
180 | class C_IO_Wrapper : public MDSIOContext | |
181 | { | |
182 | protected: | |
183 | bool async; | |
11fdf7f2 | 184 | MDSContext *wrapped; |
7c673cae FG |
185 | void finish(int r) override { |
186 | wrapped->complete(r); | |
187 | wrapped = nullptr; | |
188 | } | |
189 | public: | |
11fdf7f2 | 190 | C_IO_Wrapper(MDSRank *mds_, MDSContext *wrapped_) : |
7c673cae | 191 | MDSIOContext(mds_), async(true), wrapped(wrapped_) { |
11fdf7f2 | 192 | ceph_assert(wrapped != NULL); |
7c673cae FG |
193 | } |
194 | ||
195 | ~C_IO_Wrapper() override { | |
196 | if (wrapped != nullptr) { | |
197 | delete wrapped; | |
198 | wrapped = nullptr; | |
199 | } | |
200 | } | |
201 | void complete(int r) final; | |
91327a77 AA |
202 | void print(ostream& out) const override { |
203 | out << "io_wrapper(" << wrapped << ")"; | |
204 | } | |
7c673cae FG |
205 | }; |
206 | ||
11fdf7f2 TL |
207 | using MDSGather = C_GatherBase<MDSContext, C_MDSInternalNoop>; |
208 | using MDSGatherBuilder = C_GatherBuilderBase<MDSContext, MDSGather>; | |
7c673cae | 209 | |
11fdf7f2 | 210 | using MDSContextFactory = ContextFactory<MDSContext>; |
7c673cae FG |
211 | |
212 | #endif // MDS_CONTEXT_H |