]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_torrent.cc
update sources to v12.1.0
[ceph.git] / ceph / src / rgw / rgw_torrent.cc
1 #include <errno.h>
2 #include <stdlib.h>
3
4 #include <sstream>
5
6 #include "rgw_torrent.h"
7 #include "include/str_list.h"
8 #include "include/rados/librados.hpp"
9
10 #define dout_subsys ceph_subsys_rgw
11
12 using namespace std;
13 using ceph::crypto::MD5;
14 using namespace librados;
15 using namespace boost;
16 using ceph::crypto::SHA1;
17
18 seed::seed()
19 {
20 seed::info.piece_length = 0;
21 seed::info.len = 0;
22 sha_len = 0;
23 is_torrent = false;
24 }
25
26 seed::~seed()
27 {
28 seed::info.sha1_bl.clear();
29 bl.clear();
30 s = NULL;
31 store = NULL;
32 }
33
34 void seed::init(struct req_state *p_req, RGWRados *p_store)
35 {
36 s = p_req;
37 store = p_store;
38 }
39
40 void seed::get_torrent_file(int &op_ret, RGWRados::Object::Read &read_op, uint64_t &total_len,
41 bufferlist &bl_data, rgw_obj &obj)
42 {
43 /* add other field if config is set */
44 dencode.bencode_dict(bl);
45 set_announce();
46 if (!comment.empty())
47 {
48 dencode.bencode(COMMENT, comment, bl);
49 }
50 if (!create_by.empty())
51 {
52 dencode.bencode(CREATED_BY, create_by, bl);
53 }
54 if (!encoding.empty())
55 {
56 dencode.bencode(ENCODING, encoding, bl);
57 }
58
59 string oid, key;
60 map<string, bufferlist> m;
61 set<string> obj_key;
62 get_obj_bucket_and_oid_loc(obj, oid, key);
63 ldout(s->cct, 0) << "NOTICE: head obj oid= " << oid << dendl;
64
65 obj_key.insert(RGW_OBJ_TORRENT);
66 op_ret = read_op.state.io_ctx.omap_get_vals_by_keys(oid, obj_key, &m);
67 if (op_ret < 0)
68 {
69 ldout(s->cct, 0) << "ERROR: failed to omap_get_vals_by_keys op_ret = " << op_ret << dendl;
70 return;
71 }
72
73 map<string, bufferlist>::iterator iter;
74 for (iter = m.begin(); iter != m.end(); ++iter)
75 {
76 bufferlist bl_tmp = iter->second;
77 char *pbuff = bl_tmp.c_str();
78 bl.append(pbuff, bl_tmp.length());
79 }
80 dencode.bencode_end(bl);
81
82 bl_data = bl;
83 total_len = bl.length();
84 return;
85 }
86
87 bool seed::get_flag()
88 {
89 return is_torrent;
90 }
91
92 void seed::update(bufferlist &bl)
93 {
94 if (!is_torrent)
95 {
96 return;
97 }
98 info.len += bl.length();
99 sha1(&h, bl, bl.length());
100 }
101
102 int seed::complete()
103 {
104 uint64_t remain = info.len%info.piece_length;
105 uint8_t remain_len = ((remain > 0)? 1 : 0);
106 sha_len = (info.len/info.piece_length + remain_len)*CEPH_CRYPTO_SHA1_DIGESTSIZE;
107
108 int ret = 0;
109 /* produce torrent data */
110 do_encode();
111
112 /* save torrent data into OMAP */
113 ret = save_torrent_file();
114 if (0 != ret)
115 {
116 ldout(s->cct, 0) << "ERROR: failed to save_torrent_file() ret= "<< ret << dendl;
117 return ret;
118 }
119
120 return 0;
121 }
122
123 off_t seed::get_data_len()
124 {
125 return info.len;
126 }
127
128 void seed::set_create_date(ceph::real_time& value)
129 {
130 utime_t date = ceph::real_clock::to_timespec(value);
131 create_date = date.sec();
132 }
133
134 void seed::set_info_pieces(char *buff)
135 {
136 info.sha1_bl.append(buff, CEPH_CRYPTO_SHA1_DIGESTSIZE);
137 }
138
139 void seed::set_info_name(const string& value)
140 {
141 info.name = value;
142 }
143
144 void seed::sha1(SHA1 *h, bufferlist &bl, off_t bl_len)
145 {
146 off_t num = bl_len/info.piece_length;
147 off_t remain = 0;
148 remain = bl_len%info.piece_length;
149
150 char *pstr = bl.c_str();
151 char sha[25];
152
153 /* get sha1 */
154 for (off_t i = 0; i < num; i++)
155 {
156 memset(sha, 0x00, sizeof(sha));
157 h->Update((byte *)pstr, info.piece_length);
158 h->Final((byte *)sha);
159 set_info_pieces(sha);
160 pstr += info.piece_length;
161 }
162
163 /* process remain */
164 if (0 != remain)
165 {
166 memset(sha, 0x00, sizeof(sha));
167 h->Update((byte *)pstr, remain);
168 h->Final((byte *)sha);
169 set_info_pieces(sha);
170 }
171 }
172
173 int seed::get_params()
174 {
175 is_torrent = true;
176 info.piece_length = g_conf->rgw_torrent_sha_unit;
177 create_by = g_conf->rgw_torrent_createby;
178 encoding = g_conf->rgw_torrent_encoding;
179 origin = g_conf->rgw_torrent_origin;
180 comment = g_conf->rgw_torrent_comment;
181 announce = g_conf->rgw_torrent_tracker;
182
183 /* tracker and tracker list is empty, set announce to origin */
184 if (announce.empty() && !origin.empty())
185 {
186 announce = origin;
187 }
188
189 return 0;
190 }
191
192 void seed::set_announce()
193 {
194 list<string> announce_list; // used to get announce list from conf
195 get_str_list(announce, ",", announce_list);
196
197 if (announce_list.empty())
198 {
199 ldout(s->cct, 5) << "NOTICE: announce_list is empty " << dendl;
200 return;
201 }
202
203 list<string>::iterator iter = announce_list.begin();
204 dencode.bencode_key(ANNOUNCE, bl);
205 dencode.bencode_key((*iter), bl);
206
207 dencode.bencode_key(ANNOUNCE_LIST, bl);
208 dencode.bencode_list(bl);
209 for (; iter != announce_list.end(); ++iter)
210 {
211 dencode.bencode_list(bl);
212 dencode.bencode_key((*iter), bl);
213 dencode.bencode_end(bl);
214 }
215 dencode.bencode_end(bl);
216 }
217
218 void seed::do_encode()
219 {
220 /*Only encode create_date and sha1 info*/
221 /*Other field will be added if confi is set when run get torrent*/
222 dencode.bencode(CREATION_DATE, create_date, bl);
223
224 dencode.bencode_key(INFO_PIECES, bl);
225 dencode.bencode_dict(bl);
226 dencode.bencode(LENGTH, info.len, bl);
227 dencode.bencode(NAME, info.name, bl);
228 dencode.bencode(PIECE_LENGTH, info.piece_length, bl);
229
230 char info_sha[100] = { 0 };
231 sprintf(info_sha, "%" PRIu64, sha_len);
232 string sha_len_str = info_sha;
233 dencode.bencode_key(PIECES, bl);
234 bl.append(sha_len_str.c_str(), sha_len_str.length());
235 bl.append(':');
236 bl.append(info.sha1_bl.c_str(), sha_len);
237 dencode.bencode_end(bl);
238 }
239
240 int seed::save_torrent_file()
241 {
242 int op_ret = 0;
243 string key = RGW_OBJ_TORRENT;
244 rgw_obj obj(s->bucket, s->object.name);
245
246 rgw_raw_obj raw_obj;
247 store->obj_to_raw(s->bucket_info.placement_rule, obj, &raw_obj);
248
249 op_ret = store->omap_set(raw_obj, key, bl);
250 if (op_ret < 0)
251 {
252 ldout(s->cct, 0) << "ERROR: failed to omap_set() op_ret = " << op_ret << dendl;
253 return op_ret;
254 }
255
256 return op_ret;
257 }