Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mds / Migrator.h
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  * Handles the import and export of  mds authorities and actual cache data.
14  * See src/doc/exports.txt for a description.
15  */
16
17 #ifndef CEPH_MDS_MIGRATOR_H
18 #define CEPH_MDS_MIGRATOR_H
19
20 #include "include/types.h"
21
22 #include <map>
23 #include <list>
24 #include <set>
25 using std::map;
26 using std::list;
27 using std::set;
28
29
30 class MDSRank;
31 class CDir;
32 class CInode;
33 class CDentry;
34
35 class MExportDirDiscover;
36 class MExportDirDiscoverAck;
37 class MExportDirCancel;
38 class MExportDirPrep;
39 class MExportDirPrepAck;
40 class MExportDir;
41 class MExportDirAck;
42 class MExportDirNotify;
43 class MExportDirNotifyAck;
44 class MExportDirFinish;
45
46 class MExportCaps;
47 class MExportCapsAck;
48 class MGatherCaps;
49
50 class EImportStart;
51
52 class Migrator {
53 public:
54   // export stages.  used to clean up intelligently if there's a failure.
55   const static int EXPORT_CANCELLED     = 0;  // cancelled
56   const static int EXPORT_CANCELLING    = 1;  // waiting for cancel notifyacks
57   const static int EXPORT_LOCKING       = 2;  // acquiring locks
58   const static int EXPORT_DISCOVERING   = 3;  // dest is disovering export dir
59   const static int EXPORT_FREEZING      = 4;  // we're freezing the dir tree
60   const static int EXPORT_PREPPING      = 5;  // sending dest spanning tree to export bounds
61   const static int EXPORT_WARNING       = 6;  // warning bystanders of dir_auth_pending
62   const static int EXPORT_EXPORTING     = 7;  // sent actual export, waiting for ack
63   const static int EXPORT_LOGGINGFINISH = 8;  // logging EExportFinish
64   const static int EXPORT_NOTIFYING     = 9;  // waiting for notifyacks
65   static const char *get_export_statename(int s) {
66     switch (s) {
67     case EXPORT_CANCELLING: return "cancelling";
68     case EXPORT_LOCKING: return "locking";
69     case EXPORT_DISCOVERING: return "discovering";
70     case EXPORT_FREEZING: return "freezing";
71     case EXPORT_PREPPING: return "prepping";
72     case EXPORT_WARNING: return "warning";
73     case EXPORT_EXPORTING: return "exporting";
74     case EXPORT_LOGGINGFINISH: return "loggingfinish";
75     case EXPORT_NOTIFYING: return "notifying";
76     default: ceph_abort(); return 0;
77     }
78   }
79
80   // -- imports --
81   const static int IMPORT_DISCOVERING   = 1; // waiting for prep
82   const static int IMPORT_DISCOVERED    = 2; // waiting for prep
83   const static int IMPORT_PREPPING      = 3; // opening dirs on bounds
84   const static int IMPORT_PREPPED       = 4; // opened bounds, waiting for import
85   const static int IMPORT_LOGGINGSTART  = 5; // got import, logging EImportStart
86   const static int IMPORT_ACKING        = 6; // logged EImportStart, sent ack, waiting for finish
87   const static int IMPORT_FINISHING     = 7; // sent cap imports, waiting for finish
88   const static int IMPORT_ABORTING      = 8; // notifying bystanders of an abort before unfreezing
89   static const char *get_import_statename(int s) {
90     switch (s) {
91     case IMPORT_DISCOVERING: return "discovering";
92     case IMPORT_DISCOVERED: return "discovered";
93     case IMPORT_PREPPING: return "prepping";
94     case IMPORT_PREPPED: return "prepped";
95     case IMPORT_LOGGINGSTART: return "loggingstart";
96     case IMPORT_ACKING: return "acking";
97     case IMPORT_FINISHING: return "finishing";
98     case IMPORT_ABORTING: return "aborting";
99     default: ceph_abort(); return 0;
100     }
101   }
102
103   // -- cons --
104   Migrator(MDSRank *m, MDCache *c) : mds(m), cache(c) {}
105
106
107
108 protected:
109   // export fun
110   struct export_state_t {
111     int state;
112     mds_rank_t peer;
113     uint64_t tid;
114     set<mds_rank_t> warning_ack_waiting;
115     set<mds_rank_t> notify_ack_waiting;
116     map<inodeno_t,map<client_t,Capability::Import> > peer_imported;
117     MutationRef mut;
118     // for freeze tree deadlock detection
119     utime_t last_cum_auth_pins_change;
120     int last_cum_auth_pins;
121     int num_remote_waiters; // number of remote authpin waiters
122     export_state_t() : state(0), peer(0), tid(0), mut(),
123                        last_cum_auth_pins(0), num_remote_waiters(0) {}
124   };
125
126   map<CDir*, export_state_t>  export_state;
127
128   list<pair<dirfrag_t,mds_rank_t> >  export_queue;
129
130   // import fun
131   struct import_state_t {
132     int state;
133     mds_rank_t peer;
134     uint64_t tid;
135     set<mds_rank_t> bystanders;
136     list<dirfrag_t> bound_ls;
137     list<ScatterLock*> updated_scatterlocks;
138     map<client_t,entity_inst_t> client_map;
139     map<CInode*, map<client_t,Capability::Export> > peer_exports;
140     MutationRef mut;
141     import_state_t() : state(0), peer(0), tid(0), mut() {}
142   };
143
144   map<dirfrag_t, import_state_t>  import_state;
145
146   void handle_export_discover_ack(MExportDirDiscoverAck *m);
147   void export_frozen(CDir *dir, uint64_t tid);
148   void handle_export_prep_ack(MExportDirPrepAck *m);
149   void export_sessions_flushed(CDir *dir, uint64_t tid);
150   void export_go(CDir *dir);
151   void export_go_synced(CDir *dir, uint64_t tid);
152   void export_try_cancel(CDir *dir, bool notify_peer=true);
153   void export_cancel_finish(CDir *dir);
154   void export_reverse(CDir *dir);
155   void export_notify_abort(CDir *dir, set<CDir*>& bounds);
156   void handle_export_ack(MExportDirAck *m);
157   void export_logged_finish(CDir *dir);
158   void handle_export_notify_ack(MExportDirNotifyAck *m);
159   void export_finish(CDir *dir);
160
161   void handle_gather_caps(MGatherCaps *m);
162
163   friend class C_MDC_ExportFreeze;
164   friend class C_MDS_ExportFinishLogged;
165   friend class C_M_ExportGo;
166   friend class C_M_ExportSessionsFlushed;
167   friend class MigratorContext;
168   friend class MigratorLogContext;
169
170   // importer
171   void handle_export_discover(MExportDirDiscover *m);
172   void handle_export_cancel(MExportDirCancel *m);
173   void handle_export_prep(MExportDirPrep *m);
174   void handle_export_dir(MExportDir *m);
175
176   void import_reverse_discovering(dirfrag_t df);
177   void import_reverse_discovered(dirfrag_t df, CInode *diri);
178   void import_reverse_prepping(CDir *dir);
179   void import_remove_pins(CDir *dir, set<CDir*>& bounds);
180   void import_reverse_unfreeze(CDir *dir);
181   void import_reverse_final(CDir *dir);
182   void import_notify_abort(CDir *dir, set<CDir*>& bounds);
183   void import_notify_finish(CDir *dir, set<CDir*>& bounds);
184   void import_logged_start(dirfrag_t df, CDir *dir, mds_rank_t from,
185                            map<client_t,entity_inst_t> &imported_client_map,
186                            map<client_t,uint64_t>& sseqmap);
187   void handle_export_finish(MExportDirFinish *m);
188
189   void handle_export_caps(MExportCaps *m);
190   void logged_import_caps(CInode *in,
191                           mds_rank_t from,
192                           map<CInode*, map<client_t,Capability::Export> >& cap_imports,
193                           map<client_t,entity_inst_t>& client_map,
194                           map<client_t,uint64_t>& sseqmap);
195
196
197   friend class C_MDS_ImportDirLoggedStart;
198   friend class C_MDS_ImportDirLoggedFinish;
199   friend class C_M_LoggedImportCaps;
200
201   // bystander
202   void handle_export_notify(MExportDirNotify *m);
203
204
205 public:
206
207   void dispatch(Message*);
208
209   void show_importing();
210   void show_exporting();
211
212   int get_num_exporting() const { return export_state.size(); }
213   int get_export_queue_size() const { return export_queue.size(); }
214   
215   // -- status --
216   int is_exporting(CDir *dir) const {
217     map<CDir*, export_state_t>::const_iterator it = export_state.find(dir);
218     if (it != export_state.end()) return it->second.state;
219     return 0;
220   }
221   bool is_exporting() const { return !export_state.empty(); }
222   int is_importing(dirfrag_t df) const {
223     map<dirfrag_t, import_state_t>::const_iterator it = import_state.find(df);
224     if (it != import_state.end()) return it->second.state;
225     return 0;
226   }
227   bool is_importing() const { return !import_state.empty(); }
228
229   bool is_ambiguous_import(dirfrag_t df) const {
230     map<dirfrag_t, import_state_t>::const_iterator p = import_state.find(df);
231     if (p == import_state.end())
232       return false;
233     if (p->second.state >= IMPORT_LOGGINGSTART &&
234         p->second.state < IMPORT_ABORTING)
235       return true;
236     return false;
237   }
238
239   int get_import_state(dirfrag_t df) const {
240     map<dirfrag_t, import_state_t>::const_iterator it = import_state.find(df);
241     assert(it != import_state.end());
242     return it->second.state;
243   }
244   int get_import_peer(dirfrag_t df) const {
245     map<dirfrag_t, import_state_t>::const_iterator it = import_state.find(df);
246     assert(it != import_state.end());
247     return it->second.peer;
248   }
249
250   int get_export_state(CDir *dir) const {
251     map<CDir*, export_state_t>::const_iterator it = export_state.find(dir);
252     assert(it != export_state.end());
253     return it->second.state;
254   }
255   // this returns true if we are export @dir,
256   // and are not waiting for @who to be
257   // be warned of ambiguous auth.
258   // only returns meaningful results during EXPORT_WARNING state.
259   bool export_has_warned(CDir *dir, mds_rank_t who) {
260     map<CDir*, export_state_t>::iterator it = export_state.find(dir);
261     assert(it != export_state.end());
262     assert(it->second.state == EXPORT_WARNING);
263     return (it->second.warning_ack_waiting.count(who) == 0);
264   }
265
266   bool export_has_notified(CDir *dir, mds_rank_t who) const {
267     map<CDir*, export_state_t>::const_iterator it = export_state.find(dir);
268     assert(it != export_state.end());
269     assert(it->second.state == EXPORT_NOTIFYING);
270     return (it->second.notify_ack_waiting.count(who) == 0);
271   }
272
273   void export_freeze_inc_num_waiters(CDir *dir) {
274     map<CDir*, export_state_t>::iterator it = export_state.find(dir);
275     assert(it != export_state.end());
276     it->second.num_remote_waiters++;
277   }
278   void find_stale_export_freeze();
279
280   // -- misc --
281   void handle_mds_failure_or_stop(mds_rank_t who);
282
283   void audit();
284
285   // -- import/export --
286   // exporter
287   void dispatch_export_dir(MDRequestRef& mdr, int count);
288   void export_dir(CDir *dir, mds_rank_t dest);
289   void export_empty_import(CDir *dir);
290
291   void export_dir_nicely(CDir *dir, mds_rank_t dest);
292   void maybe_do_queued_export();
293   void clear_export_queue() {
294     export_queue.clear();
295   }
296   
297   void get_export_lock_set(CDir *dir, set<SimpleLock*>& locks);
298   void get_export_client_set(CDir *dir, set<client_t> &client_set);
299   void get_export_client_set(CInode *in, set<client_t> &client_set);
300
301   void encode_export_inode(CInode *in, bufferlist& bl, 
302                            map<client_t,entity_inst_t>& exported_client_map);
303   void encode_export_inode_caps(CInode *in, bool auth_cap, bufferlist& bl,
304                                 map<client_t,entity_inst_t>& exported_client_map);
305   void finish_export_inode(CInode *in, utime_t now, mds_rank_t target,
306                            map<client_t,Capability::Import>& peer_imported,
307                            list<MDSInternalContextBase*>& finished);
308   void finish_export_inode_caps(CInode *in, mds_rank_t target,
309                                 map<client_t,Capability::Import>& peer_imported);
310
311
312   uint64_t encode_export_dir(bufferlist& exportbl,
313                         CDir *dir,
314                         map<client_t,entity_inst_t>& exported_client_map,
315                         utime_t now);
316   void finish_export_dir(CDir *dir, utime_t now, mds_rank_t target,
317                          map<inodeno_t,map<client_t,Capability::Import> >& peer_imported,
318                          list<MDSInternalContextBase*>& finished, int *num_dentries);
319
320   void clear_export_proxy_pins(CDir *dir);
321
322   void export_caps(CInode *in);
323
324   void decode_import_inode(CDentry *dn, bufferlist::iterator& blp,
325                            mds_rank_t oldauth, LogSegment *ls,
326                            map<CInode*, map<client_t,Capability::Export> >& cap_imports,
327                            list<ScatterLock*>& updated_scatterlocks);
328   void decode_import_inode_caps(CInode *in, bool auth_cap, bufferlist::iterator &blp,
329                                 map<CInode*, map<client_t,Capability::Export> >& cap_imports);
330   void finish_import_inode_caps(CInode *in, mds_rank_t from, bool auth_cap,
331                                 map<client_t,Capability::Export> &export_map,
332                                 map<client_t,Capability::Import> &import_map);
333   int decode_import_dir(bufferlist::iterator& blp,
334                         mds_rank_t oldauth,
335                         CDir *import_root,
336                         EImportStart *le, 
337                         LogSegment *ls,
338                         map<CInode*, map<client_t,Capability::Export> >& cap_imports,
339                         list<ScatterLock*>& updated_scatterlocks, utime_t now);
340
341   void import_reverse(CDir *dir);
342
343   void import_finish(CDir *dir, bool notify, bool last=true);
344
345 private:
346   MDSRank *mds;
347   MDCache *cache;
348 };
349
350 #endif