initial code repo
[stor4nfv.git] / src / ceph / src / messages / MClientReply.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  */
14
15
16 #ifndef CEPH_MCLIENTREPLY_H
17 #define CEPH_MCLIENTREPLY_H
18
19 #include "include/types.h"
20 #include "include/fs_types.h"
21 #include "MClientRequest.h"
22
23 #include "msg/Message.h"
24 #include "include/ceph_features.h"
25 #include "common/errno.h"
26
27 /***
28  *
29  * MClientReply - container message for MDS reply to a client's MClientRequest
30  *
31  * key fields:
32  *  long tid - transaction id, so the client can match up with pending request
33  *  int result - error code, or fh if it was open
34  *
35  * for most requests:
36  *  trace is a vector of InodeStat's tracing from root to the file/dir/whatever
37  *  the operation referred to, so that the client can update it's info about what
38  *  metadata lives on what MDS.
39  *
40  * for readdir replies:
41  *  dir_contents is a vector of InodeStat*'s.  
42  * 
43  * that's mostly it, i think!
44  *
45  */
46
47
48 struct LeaseStat {
49   // this matches ceph_mds_reply_lease
50   __u16 mask;
51   __u32 duration_ms;  
52   __u32 seq;
53
54   LeaseStat() : mask(0), duration_ms(0), seq(0) {}
55
56   void encode(bufferlist &bl) const {
57     ::encode(mask, bl);
58     ::encode(duration_ms, bl);
59     ::encode(seq, bl);
60   }
61   void decode(bufferlist::iterator &bl) {
62     ::decode(mask, bl);
63     ::decode(duration_ms, bl);
64     ::decode(seq, bl);
65   }
66 };
67 WRITE_CLASS_ENCODER(LeaseStat)
68
69 inline ostream& operator<<(ostream& out, const LeaseStat& l) {
70   return out << "lease(mask " << l.mask << " dur " << l.duration_ms << ")";
71 }
72
73 struct DirStat {
74   // mds distribution hints
75   frag_t frag;
76   __s32 auth;
77   set<__s32> dist;
78   
79   DirStat() : auth(CDIR_AUTH_PARENT) {}
80   DirStat(bufferlist::iterator& p) {
81     decode(p);
82   }
83
84   void encode(bufferlist& bl) {
85     ::encode(frag, bl);
86     ::encode(auth, bl);
87     ::encode(dist, bl);
88   }
89   void decode(bufferlist::iterator& p) {
90     ::decode(frag, p);
91     ::decode(auth, p);
92     ::decode(dist, p);
93   }
94
95   // see CDir::encode_dirstat for encoder.
96 };
97
98 struct InodeStat {
99   vinodeno_t vino;
100   uint32_t rdev;
101   version_t version;
102   version_t xattr_version;
103   ceph_mds_reply_cap cap;
104   file_layout_t layout;
105   utime_t ctime, btime, mtime, atime;
106   uint32_t time_warp_seq;
107   uint64_t size, max_size;
108   uint64_t change_attr;
109   uint64_t truncate_size;
110   uint32_t truncate_seq;
111   uint32_t mode, uid, gid, nlink;
112   frag_info_t dirstat;
113   nest_info_t rstat;
114
115   fragtree_t dirfragtree;
116   string  symlink;   // symlink content (if symlink)
117
118   ceph_dir_layout dir_layout;
119
120   bufferlist xattrbl;
121
122   bufferlist inline_data;
123   version_t inline_version;
124
125   quota_info_t quota;
126
127  public:
128   InodeStat() {}
129   InodeStat(bufferlist::iterator& p, uint64_t features) {
130     decode(p, features);
131   }
132
133   void decode(bufferlist::iterator &p, uint64_t features) {
134     ::decode(vino.ino, p);
135     ::decode(vino.snapid, p);
136     ::decode(rdev, p);
137     ::decode(version, p);
138     ::decode(xattr_version, p);
139     ::decode(cap, p);
140     {
141       ceph_file_layout legacy_layout;
142       ::decode(legacy_layout, p);
143       layout.from_legacy(legacy_layout);
144     }
145     ::decode(ctime, p);
146     ::decode(mtime, p);
147     ::decode(atime, p);
148     ::decode(time_warp_seq, p);
149     ::decode(size, p);
150     ::decode(max_size, p);
151     ::decode(truncate_size, p);
152     ::decode(truncate_seq, p);
153     ::decode(mode, p);
154     ::decode(uid, p);
155     ::decode(gid, p);
156     ::decode(nlink, p);
157     ::decode(dirstat.nfiles, p);
158     ::decode(dirstat.nsubdirs, p);
159     ::decode(rstat.rbytes, p);
160     ::decode(rstat.rfiles, p);
161     ::decode(rstat.rsubdirs, p);
162     ::decode(rstat.rctime, p);
163
164     ::decode(dirfragtree, p);
165
166     ::decode(symlink, p);
167     
168     if (features & CEPH_FEATURE_DIRLAYOUTHASH)
169       ::decode(dir_layout, p);
170     else
171       memset(&dir_layout, 0, sizeof(dir_layout));
172
173     ::decode(xattrbl, p);
174
175     if (features & CEPH_FEATURE_MDS_INLINE_DATA) {
176       ::decode(inline_version, p);
177       ::decode(inline_data, p);
178     } else {
179       inline_version = CEPH_INLINE_NONE;
180     }
181
182     if (features & CEPH_FEATURE_MDS_QUOTA)
183       ::decode(quota, p);
184     else
185       memset(&quota, 0, sizeof(quota));
186
187     if ((features & CEPH_FEATURE_FS_FILE_LAYOUT_V2))
188       ::decode(layout.pool_ns, p);
189     if ((features & CEPH_FEATURE_FS_BTIME)) {
190       ::decode(btime, p);
191       ::decode(change_attr, p);
192     } else {
193       btime = utime_t();
194       change_attr = 0;
195     }
196   }
197   
198   // see CInode::encode_inodestat for encoder.
199 };
200
201
202 class MClientReply : public Message {
203   // reply data
204 public:
205   struct ceph_mds_reply_head head;
206   bufferlist trace_bl;
207   bufferlist extra_bl;
208   bufferlist snapbl;
209
210  public:
211   int get_op() const { return head.op; }
212
213   void set_mdsmap_epoch(epoch_t e) { head.mdsmap_epoch = e; }
214   epoch_t get_mdsmap_epoch() const { return head.mdsmap_epoch; }
215
216   int get_result() const {
217     return ceph_to_hostos_errno((__s32)(__u32)head.result);
218   }
219
220   void set_result(int r) { head.result = r; }
221
222   void set_unsafe() { head.safe = 0; }
223
224   bool is_safe() const { return head.safe; }
225
226   MClientReply() : Message(CEPH_MSG_CLIENT_REPLY) {}
227   MClientReply(MClientRequest *req, int result = 0) : 
228     Message(CEPH_MSG_CLIENT_REPLY) {
229     memset(&head, 0, sizeof(head));
230     header.tid = req->get_tid();
231     head.op = req->get_op();
232     head.result = result;
233     head.safe = 1;
234   }
235 private:
236   ~MClientReply() override {}
237
238 public:
239   const char *get_type_name() const override { return "creply"; }
240   void print(ostream& o) const override {
241     o << "client_reply(???:" << get_tid();
242     o << " = " << get_result();
243     if (get_result() <= 0) {
244       o << " " << cpp_strerror(get_result());
245     }
246     if (head.op & CEPH_MDS_OP_WRITE) {
247       if (head.safe)
248         o << " safe";
249       else
250         o << " unsafe";
251     }
252     o << ")";
253   }
254
255   // serialization
256   void decode_payload() override {
257     bufferlist::iterator p = payload.begin();
258     ::decode(head, p);
259     ::decode(trace_bl, p);
260     ::decode(extra_bl, p);
261     ::decode(snapbl, p);
262     assert(p.end());
263   }
264   void encode_payload(uint64_t features) override {
265     ::encode(head, payload);
266     ::encode(trace_bl, payload);
267     ::encode(extra_bl, payload);
268     ::encode(snapbl, payload);
269   }
270
271
272   // dir contents
273   void set_extra_bl(bufferlist& bl) {
274     extra_bl.claim(bl);
275   }
276   bufferlist &get_extra_bl() {
277     return extra_bl;
278   }
279
280   // trace
281   void set_trace(bufferlist& bl) {
282     trace_bl.claim(bl);
283   }
284   bufferlist& get_trace_bl() {
285     return trace_bl;
286   }
287 };
288
289 #endif