]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_period_puller.cc
7f870cbab05c8ba2b342e9bdf3ccdced8bfb987d
[ceph.git] / ceph / src / rgw / rgw_period_puller.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include "rgw_rados.h"
5 #include "rgw_zone.h"
6 #include "rgw_rest_conn.h"
7 #include "common/ceph_json.h"
8 #include "common/errno.h"
9
10 #include "services/svc_zone.h"
11
12 #define dout_subsys ceph_subsys_rgw
13
14 #undef dout_prefix
15 #define dout_prefix (*_dout << "rgw period puller: ")
16
17 RGWPeriodPuller::RGWPeriodPuller(RGWSI_Zone *zone_svc, RGWSI_SysObj *sysobj_svc)
18 {
19 cct = zone_svc->ctx();
20 svc.zone = zone_svc;
21 svc.sysobj = sysobj_svc;
22 }
23
24 namespace {
25
26 // pull the given period over the connection
27 int pull_period(RGWRESTConn* conn, const std::string& period_id,
28 const std::string& realm_id, RGWPeriod& period,
29 optional_yield y)
30 {
31 rgw_user user;
32 RGWEnv env;
33 req_info info(conn->get_ctx(), &env);
34 info.method = "GET";
35 info.request_uri = "/admin/realm/period";
36
37 auto& params = info.args.get_params();
38 params["realm_id"] = realm_id;
39 params["period_id"] = period_id;
40
41 bufferlist data;
42 #define MAX_REST_RESPONSE (128 * 1024)
43 int r = conn->forward(user, info, nullptr, MAX_REST_RESPONSE, nullptr, &data, y);
44 if (r < 0) {
45 return r;
46 }
47
48 JSONParser parser;
49 r = parser.parse(data.c_str(), data.length());
50 if (r < 0) {
51 lderr(conn->get_ctx()) << "request failed: " << cpp_strerror(-r) << dendl;
52 return r;
53 }
54
55 try {
56 decode_json_obj(period, &parser);
57 } catch (const JSONDecoder::err& e) {
58 lderr(conn->get_ctx()) << "failed to decode JSON input: "
59 << e.what() << dendl;
60 return -EINVAL;
61 }
62 return 0;
63 }
64
65 } // anonymous namespace
66
67 int RGWPeriodPuller::pull(const std::string& period_id, RGWPeriod& period,
68 optional_yield y)
69 {
70 // try to read the period from rados
71 period.set_id(period_id);
72 period.set_epoch(0);
73 int r = period.init(cct, svc.sysobj, y);
74 if (r < 0) {
75 if (svc.zone->is_meta_master()) {
76 // can't pull if we're the master
77 ldout(cct, 1) << "metadata master failed to read period "
78 << period_id << " from local storage: " << cpp_strerror(r) << dendl;
79 return r;
80 }
81 ldout(cct, 14) << "pulling period " << period_id
82 << " from master" << dendl;
83 // request the period from the master zone
84 r = pull_period(svc.zone->get_master_conn(), period_id,
85 svc.zone->get_realm().get_id(), period, y);
86 if (r < 0) {
87 lderr(cct) << "failed to pull period " << period_id << dendl;
88 return r;
89 }
90 // write the period to rados
91 r = period.store_info(true, y);
92 if (r == -EEXIST) {
93 r = 0;
94 } else if (r < 0) {
95 lderr(cct) << "failed to store period " << period_id << dendl;
96 return r;
97 }
98 // update latest epoch
99 r = period.update_latest_epoch(period.get_epoch(), y);
100 if (r == -EEXIST) {
101 // already have this epoch (or a more recent one)
102 return 0;
103 }
104 if (r < 0) {
105 lderr(cct) << "failed to update latest_epoch for period "
106 << period_id << dendl;
107 return r;
108 }
109 // reflect period objects if this is the latest version
110 if (svc.zone->get_realm().get_current_period() == period_id) {
111 r = period.reflect(y);
112 if (r < 0) {
113 return r;
114 }
115 }
116 ldout(cct, 14) << "period " << period_id
117 << " pulled and written to local storage" << dendl;
118 } else {
119 ldout(cct, 14) << "found period " << period_id
120 << " in local storage" << dendl;
121 }
122 return 0;
123 }