]>
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 | #include "common/config.h" | |
5 | #include "common/debug.h" | |
6 | ||
7 | #include "objclass/objclass.h" | |
8 | #include "osd/PrimaryLogPG.h" | |
9 | #include "osd/osd_types.h" | |
10 | ||
11 | #include "osd/ClassHandler.h" | |
12 | ||
13 | #include "auth/Crypto.h" | |
14 | #include "common/armor.h" | |
15 | ||
16 | static constexpr int dout_subsys = ceph_subsys_objclass; | |
17 | ||
18 | static ClassHandler *ch; | |
19 | ||
20 | void cls_initialize(ClassHandler *h) | |
21 | { | |
22 | ch = h; | |
23 | } | |
24 | ||
25 | void cls_finalize() | |
26 | { | |
27 | ch = NULL; | |
28 | } | |
29 | ||
30 | ||
31 | void *cls_alloc(size_t size) | |
32 | { | |
33 | return malloc(size); | |
34 | } | |
35 | ||
36 | void cls_free(void *p) | |
37 | { | |
38 | free(p); | |
39 | } | |
40 | ||
41 | int cls_register(const char *name, cls_handle_t *handle) | |
42 | { | |
43 | ClassHandler::ClassData *cls = ch->register_class(name); | |
44 | *handle = (cls_handle_t)cls; | |
45 | return (cls != NULL); | |
46 | } | |
47 | ||
48 | int cls_unregister(cls_handle_t handle) | |
49 | { | |
50 | ClassHandler::ClassData *cls = (ClassHandler::ClassData *)handle; | |
51 | ch->unregister_class(cls); | |
52 | return 1; | |
53 | } | |
54 | ||
55 | int cls_register_method(cls_handle_t hclass, const char *method, | |
56 | int flags, | |
57 | cls_method_call_t class_call, cls_method_handle_t *handle) | |
58 | { | |
59 | if (!(flags & (CLS_METHOD_RD | CLS_METHOD_WR))) | |
60 | return -EINVAL; | |
61 | ClassHandler::ClassData *cls = (ClassHandler::ClassData *)hclass; | |
62 | cls_method_handle_t hmethod =(cls_method_handle_t)cls->register_method(method, flags, class_call); | |
63 | if (handle) | |
64 | *handle = hmethod; | |
65 | return (hmethod != NULL); | |
66 | } | |
67 | ||
68 | int cls_register_cxx_method(cls_handle_t hclass, const char *method, | |
69 | int flags, | |
70 | cls_method_cxx_call_t class_call, cls_method_handle_t *handle) | |
71 | { | |
72 | ClassHandler::ClassData *cls = (ClassHandler::ClassData *)hclass; | |
73 | cls_method_handle_t hmethod = (cls_method_handle_t)cls->register_cxx_method(method, flags, class_call); | |
74 | if (handle) | |
75 | *handle = hmethod; | |
76 | return (hmethod != NULL); | |
77 | } | |
78 | ||
79 | int cls_unregister_method(cls_method_handle_t handle) | |
80 | { | |
81 | ClassHandler::ClassMethod *method = (ClassHandler::ClassMethod *)handle; | |
82 | method->unregister(); | |
83 | return 1; | |
84 | } | |
85 | ||
86 | int cls_register_cxx_filter(cls_handle_t hclass, | |
87 | const std::string &filter_name, | |
88 | cls_cxx_filter_factory_t fn, | |
89 | cls_filter_handle_t *handle) | |
90 | { | |
91 | ClassHandler::ClassData *cls = (ClassHandler::ClassData *)hclass; | |
92 | cls_filter_handle_t hfilter = (cls_filter_handle_t)cls->register_cxx_filter(filter_name, fn); | |
93 | if (handle) { | |
94 | *handle = hfilter; | |
95 | } | |
96 | return (hfilter != NULL); | |
97 | } | |
98 | ||
99 | void cls_unregister_filter(cls_filter_handle_t handle) | |
100 | { | |
101 | ClassHandler::ClassFilter *filter = (ClassHandler::ClassFilter *)handle; | |
102 | filter->unregister(); | |
103 | } | |
104 | ||
105 | int cls_call(cls_method_context_t hctx, const char *cls, const char *method, | |
106 | char *indata, int datalen, | |
107 | char **outdata, int *outdatalen) | |
108 | { | |
109 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
110 | bufferlist idata; | |
111 | vector<OSDOp> nops(1); | |
112 | OSDOp& op = nops[0]; | |
113 | int r; | |
114 | ||
115 | op.op.op = CEPH_OSD_OP_CALL; | |
116 | op.op.cls.class_len = strlen(cls); | |
117 | op.op.cls.method_len = strlen(method); | |
118 | op.op.cls.indata_len = datalen; | |
119 | op.indata.append(cls, op.op.cls.class_len); | |
120 | op.indata.append(method, op.op.cls.method_len); | |
121 | op.indata.append(indata, datalen); | |
122 | r = (*pctx)->pg->do_osd_ops(*pctx, nops); | |
123 | if (r < 0) | |
124 | return r; | |
125 | ||
126 | *outdata = (char *)malloc(op.outdata.length()); | |
127 | if (!*outdata) | |
128 | return -ENOMEM; | |
129 | memcpy(*outdata, op.outdata.c_str(), op.outdata.length()); | |
130 | *outdatalen = op.outdata.length(); | |
131 | ||
132 | return r; | |
133 | } | |
134 | ||
135 | int cls_getxattr(cls_method_context_t hctx, const char *name, | |
136 | char **outdata, int *outdatalen) | |
137 | { | |
138 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
139 | bufferlist name_data; | |
140 | vector<OSDOp> nops(1); | |
141 | OSDOp& op = nops[0]; | |
142 | int r; | |
143 | ||
144 | op.op.op = CEPH_OSD_OP_GETXATTR; | |
145 | op.indata.append(name); | |
146 | op.op.xattr.name_len = strlen(name); | |
147 | r = (*pctx)->pg->do_osd_ops(*pctx, nops); | |
148 | if (r < 0) | |
149 | return r; | |
150 | ||
151 | *outdata = (char *)malloc(op.outdata.length()); | |
152 | if (!*outdata) | |
153 | return -ENOMEM; | |
154 | memcpy(*outdata, op.outdata.c_str(), op.outdata.length()); | |
155 | *outdatalen = op.outdata.length(); | |
156 | ||
157 | return r; | |
158 | } | |
159 | ||
160 | int cls_setxattr(cls_method_context_t hctx, const char *name, | |
161 | const char *value, int val_len) | |
162 | { | |
163 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
164 | bufferlist name_data; | |
165 | vector<OSDOp> nops(1); | |
166 | OSDOp& op = nops[0]; | |
167 | int r; | |
168 | ||
169 | op.op.op = CEPH_OSD_OP_SETXATTR; | |
170 | op.indata.append(name); | |
171 | op.indata.append(value); | |
172 | op.op.xattr.name_len = strlen(name); | |
173 | op.op.xattr.value_len = val_len; | |
174 | r = (*pctx)->pg->do_osd_ops(*pctx, nops); | |
175 | ||
176 | return r; | |
177 | } | |
178 | ||
179 | int cls_read(cls_method_context_t hctx, int ofs, int len, | |
180 | char **outdata, int *outdatalen) | |
181 | { | |
182 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
183 | vector<OSDOp> ops(1); | |
184 | ops[0].op.op = CEPH_OSD_OP_SYNC_READ; | |
185 | ops[0].op.extent.offset = ofs; | |
186 | ops[0].op.extent.length = len; | |
187 | int r = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
188 | if (r < 0) | |
189 | return r; | |
190 | ||
191 | *outdata = (char *)malloc(ops[0].outdata.length()); | |
192 | if (!*outdata) | |
193 | return -ENOMEM; | |
194 | memcpy(*outdata, ops[0].outdata.c_str(), ops[0].outdata.length()); | |
195 | *outdatalen = ops[0].outdata.length(); | |
196 | ||
197 | return *outdatalen; | |
198 | } | |
199 | ||
200 | int cls_get_request_origin(cls_method_context_t hctx, entity_inst_t *origin) | |
201 | { | |
202 | PrimaryLogPG::OpContext **pctx = static_cast<PrimaryLogPG::OpContext **>(hctx); | |
203 | *origin = (*pctx)->op->get_req()->get_orig_source_inst(); | |
204 | return 0; | |
205 | } | |
206 | ||
207 | int cls_cxx_create(cls_method_context_t hctx, bool exclusive) | |
208 | { | |
209 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
210 | vector<OSDOp> ops(1); | |
211 | ops[0].op.op = CEPH_OSD_OP_CREATE; | |
212 | ops[0].op.flags = (exclusive ? CEPH_OSD_OP_FLAG_EXCL : 0); | |
213 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
214 | } | |
215 | ||
216 | int cls_cxx_remove(cls_method_context_t hctx) | |
217 | { | |
218 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
219 | vector<OSDOp> ops(1); | |
220 | ops[0].op.op = CEPH_OSD_OP_DELETE; | |
221 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
222 | } | |
223 | ||
224 | int cls_cxx_stat(cls_method_context_t hctx, uint64_t *size, time_t *mtime) | |
225 | { | |
226 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
227 | vector<OSDOp> ops(1); | |
228 | int ret; | |
229 | ops[0].op.op = CEPH_OSD_OP_STAT; | |
230 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
231 | if (ret < 0) | |
232 | return ret; | |
233 | bufferlist::iterator iter = ops[0].outdata.begin(); | |
234 | utime_t ut; | |
235 | uint64_t s; | |
236 | try { | |
237 | ::decode(s, iter); | |
238 | ::decode(ut, iter); | |
239 | } catch (buffer::error& err) { | |
240 | return -EIO; | |
241 | } | |
242 | if (size) | |
243 | *size = s; | |
244 | if (mtime) | |
245 | *mtime = ut.sec(); | |
246 | return 0; | |
247 | } | |
248 | ||
249 | int cls_cxx_stat2(cls_method_context_t hctx, uint64_t *size, ceph::real_time *mtime) | |
250 | { | |
251 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
252 | vector<OSDOp> ops(1); | |
253 | int ret; | |
254 | ops[0].op.op = CEPH_OSD_OP_STAT; | |
255 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
256 | if (ret < 0) | |
257 | return ret; | |
258 | bufferlist::iterator iter = ops[0].outdata.begin(); | |
259 | real_time ut; | |
260 | uint64_t s; | |
261 | try { | |
262 | ::decode(s, iter); | |
263 | ::decode(ut, iter); | |
264 | } catch (buffer::error& err) { | |
265 | return -EIO; | |
266 | } | |
267 | if (size) | |
268 | *size = s; | |
269 | if (mtime) | |
270 | *mtime = ut; | |
271 | return 0; | |
272 | } | |
273 | ||
274 | int cls_cxx_read(cls_method_context_t hctx, int ofs, int len, bufferlist *outbl) | |
275 | { | |
276 | return cls_cxx_read2(hctx, ofs, len, outbl, 0); | |
277 | } | |
278 | ||
279 | int cls_cxx_read2(cls_method_context_t hctx, int ofs, int len, | |
280 | bufferlist *outbl, uint32_t op_flags) | |
281 | { | |
282 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
283 | vector<OSDOp> ops(1); | |
284 | int ret; | |
285 | ops[0].op.op = CEPH_OSD_OP_SYNC_READ; | |
286 | ops[0].op.extent.offset = ofs; | |
287 | ops[0].op.extent.length = len; | |
288 | ops[0].op.flags = op_flags; | |
289 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
290 | if (ret < 0) | |
291 | return ret; | |
292 | outbl->claim(ops[0].outdata); | |
293 | return outbl->length(); | |
294 | } | |
295 | ||
296 | int cls_cxx_write(cls_method_context_t hctx, int ofs, int len, bufferlist *inbl) | |
297 | { | |
298 | return cls_cxx_write2(hctx, ofs, len, inbl, 0); | |
299 | } | |
300 | ||
301 | int cls_cxx_write2(cls_method_context_t hctx, int ofs, int len, | |
302 | bufferlist *inbl, uint32_t op_flags) | |
303 | { | |
304 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
305 | vector<OSDOp> ops(1); | |
306 | ops[0].op.op = CEPH_OSD_OP_WRITE; | |
307 | ops[0].op.extent.offset = ofs; | |
308 | ops[0].op.extent.length = len; | |
309 | ops[0].op.flags = op_flags; | |
310 | ops[0].indata = *inbl; | |
311 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
312 | } | |
313 | ||
314 | int cls_cxx_write_full(cls_method_context_t hctx, bufferlist *inbl) | |
315 | { | |
316 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
317 | vector<OSDOp> ops(1); | |
318 | ops[0].op.op = CEPH_OSD_OP_WRITEFULL; | |
319 | ops[0].op.extent.offset = 0; | |
320 | ops[0].op.extent.length = inbl->length(); | |
321 | ops[0].indata = *inbl; | |
322 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
323 | } | |
324 | ||
325 | int cls_cxx_replace(cls_method_context_t hctx, int ofs, int len, bufferlist *inbl) | |
326 | { | |
327 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
328 | vector<OSDOp> ops(2); | |
329 | ops[0].op.op = CEPH_OSD_OP_TRUNCATE; | |
330 | ops[0].op.extent.offset = 0; | |
331 | ops[0].op.extent.length = 0; | |
332 | ops[1].op.op = CEPH_OSD_OP_WRITE; | |
333 | ops[1].op.extent.offset = ofs; | |
334 | ops[1].op.extent.length = len; | |
335 | ops[1].indata = *inbl; | |
336 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
337 | } | |
338 | ||
339 | int cls_cxx_getxattr(cls_method_context_t hctx, const char *name, | |
340 | bufferlist *outbl) | |
341 | { | |
342 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
343 | bufferlist name_data; | |
344 | vector<OSDOp> nops(1); | |
345 | OSDOp& op = nops[0]; | |
346 | int r; | |
347 | ||
348 | op.op.op = CEPH_OSD_OP_GETXATTR; | |
349 | op.indata.append(name); | |
350 | op.op.xattr.name_len = strlen(name); | |
351 | r = (*pctx)->pg->do_osd_ops(*pctx, nops); | |
352 | if (r < 0) | |
353 | return r; | |
354 | ||
355 | outbl->claim(op.outdata); | |
356 | return outbl->length(); | |
357 | } | |
358 | ||
359 | int cls_cxx_getxattrs(cls_method_context_t hctx, map<string, bufferlist> *attrset) | |
360 | { | |
361 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
362 | vector<OSDOp> nops(1); | |
363 | OSDOp& op = nops[0]; | |
364 | int r; | |
365 | ||
366 | op.op.op = CEPH_OSD_OP_GETXATTRS; | |
367 | r = (*pctx)->pg->do_osd_ops(*pctx, nops); | |
368 | if (r < 0) | |
369 | return r; | |
370 | ||
371 | bufferlist::iterator iter = op.outdata.begin(); | |
372 | try { | |
373 | ::decode(*attrset, iter); | |
374 | } catch (buffer::error& err) { | |
375 | return -EIO; | |
376 | } | |
377 | return 0; | |
378 | } | |
379 | ||
380 | int cls_cxx_setxattr(cls_method_context_t hctx, const char *name, | |
381 | bufferlist *inbl) | |
382 | { | |
383 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
384 | bufferlist name_data; | |
385 | vector<OSDOp> nops(1); | |
386 | OSDOp& op = nops[0]; | |
387 | int r; | |
388 | ||
389 | op.op.op = CEPH_OSD_OP_SETXATTR; | |
390 | op.indata.append(name); | |
391 | op.indata.append(*inbl); | |
392 | op.op.xattr.name_len = strlen(name); | |
393 | op.op.xattr.value_len = inbl->length(); | |
394 | r = (*pctx)->pg->do_osd_ops(*pctx, nops); | |
395 | ||
396 | return r; | |
397 | } | |
398 | ||
399 | int cls_cxx_snap_revert(cls_method_context_t hctx, snapid_t snapid) | |
400 | { | |
401 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
402 | vector<OSDOp> ops(1); | |
403 | ops[0].op.op = CEPH_OSD_OP_ROLLBACK; | |
404 | ops[0].op.snap.snapid = snapid; | |
405 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
406 | } | |
407 | ||
c07f9fc5 FG |
408 | int cls_cxx_map_get_all_vals(cls_method_context_t hctx, map<string, bufferlist>* vals, |
409 | bool *more) | |
7c673cae FG |
410 | { |
411 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
412 | vector<OSDOp> ops(1); | |
413 | OSDOp& op = ops[0]; | |
414 | int ret; | |
415 | ||
416 | string start_after; | |
417 | string filter_prefix; | |
418 | uint64_t max = (uint64_t)-1; | |
419 | ||
420 | ::encode(start_after, op.indata); | |
421 | ::encode(max, op.indata); | |
422 | ::encode(filter_prefix, op.indata); | |
423 | ||
424 | op.op.op = CEPH_OSD_OP_OMAPGETVALS; | |
425 | ||
426 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
427 | if (ret < 0) | |
428 | return ret; | |
429 | ||
430 | bufferlist::iterator iter = op.outdata.begin(); | |
431 | try { | |
432 | ::decode(*vals, iter); | |
c07f9fc5 | 433 | ::decode(*more, iter); |
7c673cae FG |
434 | } catch (buffer::error& err) { |
435 | return -EIO; | |
436 | } | |
437 | return vals->size(); | |
438 | } | |
439 | ||
440 | int cls_cxx_map_get_keys(cls_method_context_t hctx, const string &start_obj, | |
c07f9fc5 FG |
441 | uint64_t max_to_get, set<string> *keys, |
442 | bool *more) | |
7c673cae FG |
443 | { |
444 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
445 | vector<OSDOp> ops(1); | |
446 | OSDOp& op = ops[0]; | |
447 | int ret; | |
448 | ||
449 | ::encode(start_obj, op.indata); | |
450 | ::encode(max_to_get, op.indata); | |
451 | ||
452 | op.op.op = CEPH_OSD_OP_OMAPGETKEYS; | |
453 | ||
454 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
455 | if (ret < 0) | |
456 | return ret; | |
457 | ||
458 | bufferlist::iterator iter = op.outdata.begin(); | |
459 | try { | |
460 | ::decode(*keys, iter); | |
c07f9fc5 | 461 | ::decode(*more, iter); |
7c673cae FG |
462 | } catch (buffer::error& err) { |
463 | return -EIO; | |
464 | } | |
465 | return keys->size(); | |
466 | } | |
467 | ||
468 | int cls_cxx_map_get_vals(cls_method_context_t hctx, const string &start_obj, | |
469 | const string &filter_prefix, uint64_t max_to_get, | |
c07f9fc5 | 470 | map<string, bufferlist> *vals, bool *more) |
7c673cae FG |
471 | { |
472 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
473 | vector<OSDOp> ops(1); | |
474 | OSDOp& op = ops[0]; | |
475 | int ret; | |
476 | ||
477 | ::encode(start_obj, op.indata); | |
478 | ::encode(max_to_get, op.indata); | |
479 | ::encode(filter_prefix, op.indata); | |
480 | ||
481 | op.op.op = CEPH_OSD_OP_OMAPGETVALS; | |
482 | ||
483 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
484 | if (ret < 0) | |
485 | return ret; | |
486 | ||
487 | bufferlist::iterator iter = op.outdata.begin(); | |
488 | try { | |
489 | ::decode(*vals, iter); | |
c07f9fc5 | 490 | ::decode(*more, iter); |
7c673cae FG |
491 | } catch (buffer::error& err) { |
492 | return -EIO; | |
493 | } | |
494 | return vals->size(); | |
495 | } | |
496 | ||
497 | int cls_cxx_map_read_header(cls_method_context_t hctx, bufferlist *outbl) | |
498 | { | |
499 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
500 | vector<OSDOp> ops(1); | |
501 | OSDOp& op = ops[0]; | |
502 | int ret; | |
503 | op.op.op = CEPH_OSD_OP_OMAPGETHEADER; | |
504 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
505 | if (ret < 0) | |
506 | return ret; | |
507 | ||
508 | outbl->claim(op.outdata); | |
509 | ||
510 | return 0; | |
511 | } | |
512 | ||
513 | int cls_cxx_map_get_val(cls_method_context_t hctx, const string &key, | |
514 | bufferlist *outbl) | |
515 | { | |
516 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
517 | vector<OSDOp> ops(1); | |
518 | OSDOp& op = ops[0]; | |
519 | int ret; | |
520 | ||
521 | set<string> k; | |
522 | k.insert(key); | |
523 | ::encode(k, op.indata); | |
524 | ||
525 | op.op.op = CEPH_OSD_OP_OMAPGETVALSBYKEYS; | |
526 | ret = (*pctx)->pg->do_osd_ops(*pctx, ops); | |
527 | if (ret < 0) | |
528 | return ret; | |
529 | ||
530 | bufferlist::iterator iter = op.outdata.begin(); | |
531 | try { | |
532 | map<string, bufferlist> m; | |
533 | ||
534 | ::decode(m, iter); | |
535 | map<string, bufferlist>::iterator iter = m.begin(); | |
536 | if (iter == m.end()) | |
537 | return -ENOENT; | |
538 | ||
539 | *outbl = iter->second; | |
540 | } catch (buffer::error& e) { | |
541 | return -EIO; | |
542 | } | |
543 | return 0; | |
544 | } | |
545 | ||
546 | int cls_cxx_map_set_val(cls_method_context_t hctx, const string &key, | |
547 | bufferlist *inbl) | |
548 | { | |
549 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
550 | vector<OSDOp> ops(1); | |
551 | OSDOp& op = ops[0]; | |
552 | bufferlist& update_bl = op.indata; | |
553 | map<string, bufferlist> m; | |
554 | m[key] = *inbl; | |
555 | ::encode(m, update_bl); | |
556 | ||
557 | op.op.op = CEPH_OSD_OP_OMAPSETVALS; | |
558 | ||
559 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
560 | } | |
561 | ||
562 | int cls_cxx_map_set_vals(cls_method_context_t hctx, | |
563 | const std::map<string, bufferlist> *map) | |
564 | { | |
565 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
566 | vector<OSDOp> ops(1); | |
567 | OSDOp& op = ops[0]; | |
568 | bufferlist& update_bl = op.indata; | |
569 | ::encode(*map, update_bl); | |
570 | ||
571 | op.op.op = CEPH_OSD_OP_OMAPSETVALS; | |
572 | ||
573 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
574 | } | |
575 | ||
576 | int cls_cxx_map_clear(cls_method_context_t hctx) | |
577 | { | |
578 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
579 | vector<OSDOp> ops(1); | |
580 | OSDOp& op = ops[0]; | |
581 | ||
582 | op.op.op = CEPH_OSD_OP_OMAPCLEAR; | |
583 | ||
584 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
585 | } | |
586 | ||
587 | int cls_cxx_map_write_header(cls_method_context_t hctx, bufferlist *inbl) | |
588 | { | |
589 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
590 | vector<OSDOp> ops(1); | |
591 | OSDOp& op = ops[0]; | |
592 | op.indata.claim(*inbl); | |
593 | ||
594 | op.op.op = CEPH_OSD_OP_OMAPSETHEADER; | |
595 | ||
596 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
597 | } | |
598 | ||
599 | int cls_cxx_map_remove_key(cls_method_context_t hctx, const string &key) | |
600 | { | |
601 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
602 | vector<OSDOp> ops(1); | |
603 | OSDOp& op = ops[0]; | |
604 | bufferlist& update_bl = op.indata; | |
605 | set<string> to_rm; | |
606 | to_rm.insert(key); | |
607 | ||
608 | ::encode(to_rm, update_bl); | |
609 | ||
610 | op.op.op = CEPH_OSD_OP_OMAPRMKEYS; | |
611 | ||
612 | return (*pctx)->pg->do_osd_ops(*pctx, ops); | |
613 | } | |
614 | ||
615 | int cls_cxx_list_watchers(cls_method_context_t hctx, | |
616 | obj_list_watch_response_t *watchers) | |
617 | { | |
618 | PrimaryLogPG::OpContext **pctx = (PrimaryLogPG::OpContext **)hctx; | |
619 | vector<OSDOp> nops(1); | |
620 | OSDOp& op = nops[0]; | |
621 | int r; | |
622 | ||
623 | op.op.op = CEPH_OSD_OP_LIST_WATCHERS; | |
624 | r = (*pctx)->pg->do_osd_ops(*pctx, nops); | |
625 | if (r < 0) | |
626 | return r; | |
627 | ||
628 | bufferlist::iterator iter = op.outdata.begin(); | |
629 | try { | |
630 | ::decode(*watchers, iter); | |
631 | } catch (buffer::error& err) { | |
632 | return -EIO; | |
633 | } | |
634 | return 0; | |
635 | } | |
636 | ||
637 | int cls_gen_random_bytes(char *buf, int size) | |
638 | { | |
639 | return get_random_bytes(buf, size); | |
640 | } | |
641 | ||
642 | int cls_gen_rand_base64(char *dest, int size) /* size should be the required string size + 1 */ | |
643 | { | |
644 | char buf[size]; | |
645 | char tmp_dest[size + 4]; /* so that there's space for the extra '=' characters, and some */ | |
646 | int ret; | |
647 | ||
648 | ret = cls_gen_random_bytes(buf, sizeof(buf)); | |
649 | if (ret < 0) { | |
650 | lgeneric_derr(ch->cct) << "cannot get random bytes: " << ret << dendl; | |
651 | return -1; | |
652 | } | |
653 | ||
654 | ret = ceph_armor(tmp_dest, &tmp_dest[sizeof(tmp_dest)], | |
655 | (const char *)buf, ((const char *)buf) + ((size - 1) * 3 + 4 - 1) / 4); | |
656 | if (ret < 0) { | |
657 | lgeneric_derr(ch->cct) << "ceph_armor failed" << dendl; | |
658 | return -1; | |
659 | } | |
660 | tmp_dest[ret] = '\0'; | |
661 | memcpy(dest, tmp_dest, size); | |
662 | dest[size-1] = '\0'; | |
663 | ||
664 | return 0; | |
665 | } | |
666 | ||
667 | uint64_t cls_current_version(cls_method_context_t hctx) | |
668 | { | |
669 | PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; | |
670 | ||
671 | return ctx->pg->info.last_user_version; | |
672 | } | |
673 | ||
674 | ||
675 | int cls_current_subop_num(cls_method_context_t hctx) | |
676 | { | |
677 | PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; | |
678 | ||
679 | return ctx->current_osd_subop_num; | |
680 | } | |
681 | ||
682 | uint64_t cls_get_features(cls_method_context_t hctx) | |
683 | { | |
684 | PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; | |
685 | return ctx->pg->get_osdmap()->get_up_osd_features(); | |
686 | } | |
687 | ||
688 | uint64_t cls_get_client_features(cls_method_context_t hctx) | |
689 | { | |
690 | PrimaryLogPG::OpContext *ctx = *(PrimaryLogPG::OpContext **)hctx; | |
691 | return ctx->op->get_req()->get_connection()->get_features(); | |
692 | } | |
693 | ||
694 | void cls_cxx_subop_version(cls_method_context_t hctx, string *s) | |
695 | { | |
696 | if (!s) | |
697 | return; | |
698 | ||
699 | char buf[32]; | |
700 | uint64_t ver = cls_current_version(hctx); | |
701 | int subop_num = cls_current_subop_num(hctx); | |
702 | snprintf(buf, sizeof(buf), "%lld.%d", (long long)ver, subop_num); | |
703 | ||
704 | *s = buf; | |
705 | } | |
706 | ||
707 | int cls_log(int level, const char *format, ...) | |
708 | { | |
709 | int size = 256; | |
710 | va_list ap; | |
711 | while (1) { | |
712 | char buf[size]; | |
713 | va_start(ap, format); | |
714 | int n = vsnprintf(buf, size, format, ap); | |
715 | va_end(ap); | |
716 | #define MAX_SIZE 8196 | |
717 | if ((n > -1 && n < size) || size > MAX_SIZE) { | |
718 | ldout(ch->cct, level) << buf << dendl; | |
719 | return n; | |
720 | } | |
721 | size *= 2; | |
722 | } | |
723 | } |