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