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