]>
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) 2004-2006 Sage Weil <sage@newdream.net> | |
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 | #include "MDSTable.h" | |
16 | ||
17 | #include "MDSRank.h" | |
18 | #include "MDLog.h" | |
19 | ||
20 | #include "osdc/Filer.h" | |
21 | ||
22 | #include "include/types.h" | |
23 | ||
24 | #include "common/config.h" | |
25 | #include "common/errno.h" | |
26 | #include "common/Finisher.h" | |
27 | ||
11fdf7f2 | 28 | #include "include/ceph_assert.h" |
7c673cae FG |
29 | |
30 | ||
31 | #define dout_context g_ceph_context | |
32 | #define dout_subsys ceph_subsys_mds | |
33 | #undef dout_prefix | |
34 | #define dout_prefix *_dout << "mds." << rank << "." << table_name << ": " | |
35 | ||
36 | ||
37 | class MDSTableIOContext : public MDSIOContextBase | |
38 | { | |
39 | protected: | |
40 | MDSTable *ida; | |
41 | MDSRank *get_mds() override {return ida->mds;} | |
42 | public: | |
43 | explicit MDSTableIOContext(MDSTable *ida_) : ida(ida_) { | |
11fdf7f2 | 44 | ceph_assert(ida != NULL); |
7c673cae FG |
45 | } |
46 | }; | |
47 | ||
48 | ||
49 | class C_IO_MT_Save : public MDSTableIOContext { | |
50 | version_t version; | |
51 | public: | |
52 | C_IO_MT_Save(MDSTable *i, version_t v) : MDSTableIOContext(i), version(v) {} | |
53 | void finish(int r) override { | |
54 | ida->save_2(r, version); | |
55 | } | |
91327a77 AA |
56 | void print(ostream& out) const override { |
57 | out << "table_save(" << ida->table_name << ")"; | |
58 | } | |
7c673cae FG |
59 | }; |
60 | ||
11fdf7f2 | 61 | void MDSTable::save(MDSContext *onfinish, version_t v) |
7c673cae FG |
62 | { |
63 | if (v > 0 && v <= committing_version) { | |
64 | dout(10) << "save v " << version << " - already saving " | |
65 | << committing_version << " >= needed " << v << dendl; | |
11fdf7f2 TL |
66 | if (onfinish) |
67 | waitfor_save[v].push_back(onfinish); | |
7c673cae FG |
68 | return; |
69 | } | |
70 | ||
71 | dout(10) << "save v " << version << dendl; | |
11fdf7f2 | 72 | ceph_assert(is_active()); |
7c673cae FG |
73 | |
74 | bufferlist bl; | |
11fdf7f2 | 75 | encode(version, bl); |
7c673cae FG |
76 | encode_state(bl); |
77 | ||
78 | committing_version = version; | |
79 | ||
80 | if (onfinish) | |
81 | waitfor_save[version].push_back(onfinish); | |
82 | ||
83 | // write (async) | |
84 | SnapContext snapc; | |
85 | object_t oid = get_object_name(); | |
86 | object_locator_t oloc(mds->mdsmap->get_metadata_pool()); | |
87 | mds->objecter->write_full(oid, oloc, | |
88 | snapc, | |
89 | bl, ceph::real_clock::now(), 0, | |
90 | new C_OnFinisher(new C_IO_MT_Save(this, version), | |
91 | mds->finisher)); | |
92 | } | |
93 | ||
94 | void MDSTable::save_2(int r, version_t v) | |
95 | { | |
96 | if (r < 0) { | |
97 | dout(1) << "save error " << r << " v " << v << dendl; | |
98 | mds->clog->error() << "failed to store table " << table_name << " object," | |
99 | << " errno " << r; | |
100 | mds->handle_write_error(r); | |
101 | return; | |
102 | } | |
103 | ||
104 | dout(10) << "save_2 v " << v << dendl; | |
105 | committed_version = v; | |
106 | ||
11fdf7f2 | 107 | MDSContext::vec ls; |
7c673cae | 108 | while (!waitfor_save.empty()) { |
11fdf7f2 TL |
109 | auto it = waitfor_save.begin(); |
110 | if (it->first > v) break; | |
111 | auto& v = it->second; | |
112 | ls.insert(ls.end(), v.begin(), v.end()); | |
113 | waitfor_save.erase(it); | |
7c673cae | 114 | } |
11fdf7f2 | 115 | finish_contexts(g_ceph_context, ls, 0); |
7c673cae FG |
116 | } |
117 | ||
118 | ||
119 | void MDSTable::reset() | |
120 | { | |
121 | reset_state(); | |
11fdf7f2 | 122 | projected_version = version; |
7c673cae FG |
123 | state = STATE_ACTIVE; |
124 | } | |
125 | ||
126 | ||
127 | ||
128 | // ----------------------- | |
129 | ||
130 | class C_IO_MT_Load : public MDSTableIOContext { | |
131 | public: | |
132 | Context *onfinish; | |
133 | bufferlist bl; | |
134 | C_IO_MT_Load(MDSTable *i, Context *o) : MDSTableIOContext(i), onfinish(o) {} | |
135 | void finish(int r) override { | |
136 | ida->load_2(r, bl, onfinish); | |
137 | } | |
91327a77 AA |
138 | void print(ostream& out) const override { |
139 | out << "table_load(" << ida->table_name << ")"; | |
140 | } | |
7c673cae FG |
141 | }; |
142 | ||
143 | object_t MDSTable::get_object_name() const | |
144 | { | |
145 | char n[50]; | |
146 | if (per_mds) | |
11fdf7f2 | 147 | snprintf(n, sizeof(n), "mds%d_%s", int(rank), table_name.c_str()); |
7c673cae | 148 | else |
11fdf7f2 | 149 | snprintf(n, sizeof(n), "mds_%s", table_name.c_str()); |
7c673cae FG |
150 | return object_t(n); |
151 | } | |
152 | ||
11fdf7f2 | 153 | void MDSTable::load(MDSContext *onfinish) |
7c673cae FG |
154 | { |
155 | dout(10) << "load" << dendl; | |
156 | ||
11fdf7f2 | 157 | ceph_assert(is_undef()); |
7c673cae FG |
158 | state = STATE_OPENING; |
159 | ||
160 | C_IO_MT_Load *c = new C_IO_MT_Load(this, onfinish); | |
161 | object_t oid = get_object_name(); | |
162 | object_locator_t oloc(mds->mdsmap->get_metadata_pool()); | |
163 | mds->objecter->read_full(oid, oloc, CEPH_NOSNAP, &c->bl, 0, | |
164 | new C_OnFinisher(c, mds->finisher)); | |
165 | } | |
166 | ||
167 | void MDSTable::load_2(int r, bufferlist& bl, Context *onfinish) | |
168 | { | |
11fdf7f2 | 169 | ceph_assert(is_opening()); |
7c673cae FG |
170 | state = STATE_ACTIVE; |
171 | if (r == -EBLACKLISTED) { | |
172 | mds->respawn(); | |
173 | return; | |
174 | } | |
175 | if (r < 0) { | |
176 | derr << "load_2 could not read table: " << r << dendl; | |
177 | mds->clog->error() << "error reading table object '" << get_object_name() | |
178 | << "' " << r << " (" << cpp_strerror(r) << ")"; | |
179 | mds->damaged(); | |
11fdf7f2 | 180 | ceph_assert(r >= 0); // Should be unreachable because damaged() calls respawn() |
7c673cae FG |
181 | } |
182 | ||
183 | dout(10) << "load_2 got " << bl.length() << " bytes" << dendl; | |
11fdf7f2 | 184 | auto p = bl.cbegin(); |
7c673cae FG |
185 | |
186 | try { | |
11fdf7f2 | 187 | decode(version, p); |
7c673cae FG |
188 | projected_version = committed_version = version; |
189 | dout(10) << "load_2 loaded v" << version << dendl; | |
190 | decode_state(p); | |
191 | } catch (buffer::error &e) { | |
192 | mds->clog->error() << "error decoding table object '" << get_object_name() | |
193 | << "': " << e.what(); | |
194 | mds->damaged(); | |
11fdf7f2 | 195 | ceph_assert(r >= 0); // Should be unreachable because damaged() calls respawn() |
7c673cae FG |
196 | } |
197 | ||
198 | if (onfinish) { | |
199 | onfinish->complete(0); | |
200 | } | |
201 | } |