Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 int seed::get_torrent_file(RGWRados::Object::Read &read_op,
41                            uint64_t &total_len,
42                            ceph::bufferlist &bl_data,
43                            rgw_obj &obj)
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);
68   const int op_ret = read_op.state.io_ctx.omap_get_vals_by_keys(oid, obj_key, &m);
69   if (op_ret < 0)
70   {
71     ldout(s->cct, 0) << "ERROR: failed to omap_get_vals_by_keys op_ret = "
72                      << op_ret << dendl;
73     return op_ret;
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();
87   return 0;
88 }
89
90 bool seed::get_flag()
91 {
92   return is_torrent;
93 }
94
95 void seed::update(bufferlist &bl)
96 {
97   if (!is_torrent)
98   {
99     return;
100   }
101   info.len += bl.length();
102   sha1(&h, bl, bl.length());
103 }
104
105 int 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;
124 }
125
126 off_t seed::get_data_len()
127 {
128   return info.len;
129 }
130
131 void 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
137 void seed::set_info_pieces(char *buff)
138 {
139   info.sha1_bl.append(buff, CEPH_CRYPTO_SHA1_DIGESTSIZE);
140 }
141
142 void seed::set_info_name(const string& value)
143 {
144   info.name = value;
145 }
146
147 void 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
176 int 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
195 void 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
221 void 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
243 int 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 }