initial code repo
[stor4nfv.git] / src / ceph / src / rgw / rgw_torrent.cc
diff --git a/src/ceph/src/rgw/rgw_torrent.cc b/src/ceph/src/rgw/rgw_torrent.cc
new file mode 100644 (file)
index 0000000..ad85148
--- /dev/null
@@ -0,0 +1,260 @@
+#include <errno.h>
+#include <stdlib.h>
+
+#include <sstream>
+
+#include "rgw_torrent.h"
+#include "include/str_list.h"
+#include "include/rados/librados.hpp"
+
+#define dout_subsys ceph_subsys_rgw
+
+using namespace std;
+using ceph::crypto::MD5;
+using namespace librados;
+using namespace boost;
+using ceph::crypto::SHA1;
+
+seed::seed()
+{
+  seed::info.piece_length = 0;
+  seed::info.len = 0;
+  sha_len = 0;
+  is_torrent = false; 
+}
+
+seed::~seed()
+{
+  seed::info.sha1_bl.clear();
+  bl.clear();
+  s = NULL;
+  store = NULL;
+}
+
+void seed::init(struct req_state *p_req, RGWRados *p_store)
+{
+  s = p_req;
+  store = p_store;
+}
+
+int seed::get_torrent_file(RGWRados::Object::Read &read_op,
+                           uint64_t &total_len,
+                           ceph::bufferlist &bl_data,
+                           rgw_obj &obj)
+{
+  /* add other field if config is set */
+  dencode.bencode_dict(bl);
+  set_announce();
+  if (!comment.empty())
+  {
+    dencode.bencode(COMMENT, comment, bl);
+  }
+  if (!create_by.empty())
+  {
+    dencode.bencode(CREATED_BY, create_by, bl);
+  }
+  if (!encoding.empty())
+  {
+    dencode.bencode(ENCODING, encoding, bl);
+  }
+
+  string oid, key;
+  map<string, bufferlist> m;
+  set<string> obj_key;
+  get_obj_bucket_and_oid_loc(obj, oid, key);
+  ldout(s->cct, 0) << "NOTICE: head obj oid= " << oid << dendl;
+
+  obj_key.insert(RGW_OBJ_TORRENT);
+  const int op_ret = read_op.state.io_ctx.omap_get_vals_by_keys(oid, obj_key, &m);
+  if (op_ret < 0)
+  {
+    ldout(s->cct, 0) << "ERROR: failed to omap_get_vals_by_keys op_ret = "
+                     << op_ret << dendl;
+    return op_ret;
+  }
+
+  map<string, bufferlist>::iterator iter;
+  for (iter = m.begin(); iter != m.end(); ++iter)
+  {
+    bufferlist bl_tmp = iter->second;
+    char *pbuff = bl_tmp.c_str();
+    bl.append(pbuff, bl_tmp.length());
+  }
+  dencode.bencode_end(bl);
+
+  bl_data = bl;
+  total_len = bl.length();
+  return 0;
+}
+
+bool seed::get_flag()
+{
+  return is_torrent;
+}
+
+void seed::update(bufferlist &bl)
+{
+  if (!is_torrent)
+  {
+    return;
+  }
+  info.len += bl.length();
+  sha1(&h, bl, bl.length());
+}
+
+int seed::complete()
+{
+  uint64_t remain = info.len%info.piece_length;
+  uint8_t  remain_len = ((remain > 0)? 1 : 0);
+  sha_len = (info.len/info.piece_length + remain_len)*CEPH_CRYPTO_SHA1_DIGESTSIZE;
+
+  int ret = 0;
+   /* produce torrent data */
+  do_encode();
+
+  /* save torrent data into OMAP */
+  ret = save_torrent_file();
+  if (0 != ret)
+  {
+    ldout(s->cct, 0) << "ERROR: failed to save_torrent_file() ret= "<< ret << dendl;
+    return ret;
+  }
+
+  return 0;
+}
+
+off_t seed::get_data_len()
+{
+  return info.len;
+}
+
+void seed::set_create_date(ceph::real_time& value)
+{
+  utime_t date = ceph::real_clock::to_timespec(value);
+  create_date = date.sec();
+}
+
+void seed::set_info_pieces(char *buff)
+{
+  info.sha1_bl.append(buff, CEPH_CRYPTO_SHA1_DIGESTSIZE);
+}
+
+void seed::set_info_name(const string& value)
+{
+  info.name = value;
+}
+
+void seed::sha1(SHA1 *h, bufferlist &bl, off_t bl_len)
+{
+  off_t num = bl_len/info.piece_length;
+  off_t remain = 0;
+  remain = bl_len%info.piece_length;
+
+  char *pstr = bl.c_str();
+  char sha[25];
+
+  /* get sha1 */
+  for (off_t i = 0; i < num; i++)
+  {
+    memset(sha, 0x00, sizeof(sha));
+    h->Update((byte *)pstr, info.piece_length);
+    h->Final((byte *)sha);
+    set_info_pieces(sha);
+    pstr += info.piece_length;
+  }
+
+  /* process remain */
+  if (0 != remain)
+  {
+    memset(sha, 0x00, sizeof(sha));
+    h->Update((byte *)pstr, remain);
+    h->Final((byte *)sha);
+    set_info_pieces(sha);
+  }
+}
+
+int seed::get_params()
+{
+  is_torrent = true;
+  info.piece_length = g_conf->rgw_torrent_sha_unit;
+  create_by = g_conf->rgw_torrent_createby;
+  encoding = g_conf->rgw_torrent_encoding;
+  origin = g_conf->rgw_torrent_origin;
+  comment = g_conf->rgw_torrent_comment;
+  announce = g_conf->rgw_torrent_tracker;
+
+  /* tracker and tracker list is empty, set announce to origin */
+  if (announce.empty() && !origin.empty())
+  {
+    announce = origin;
+  }
+
+  return 0;
+}
+
+void seed::set_announce()
+{
+  list<string> announce_list;  // used to get announce list from conf
+  get_str_list(announce, ",", announce_list);
+
+  if (announce_list.empty())
+  {
+    ldout(s->cct, 5) << "NOTICE: announce_list is empty " << dendl;    
+    return;
+  }
+
+  list<string>::iterator iter = announce_list.begin();
+  dencode.bencode_key(ANNOUNCE, bl);
+  dencode.bencode_key((*iter), bl);
+
+  dencode.bencode_key(ANNOUNCE_LIST, bl);
+  dencode.bencode_list(bl);
+  for (; iter != announce_list.end(); ++iter)
+  {
+    dencode.bencode_list(bl);
+    dencode.bencode_key((*iter), bl);
+    dencode.bencode_end(bl);
+  }
+  dencode.bencode_end(bl);
+}
+
+void seed::do_encode()
+{ 
+  /*Only encode create_date and sha1 info*/
+  /*Other field will be added if confi is set when run get torrent*/
+  dencode.bencode(CREATION_DATE, create_date, bl);
+
+  dencode.bencode_key(INFO_PIECES, bl);
+  dencode.bencode_dict(bl);  
+  dencode.bencode(LENGTH, info.len, bl);
+  dencode.bencode(NAME, info.name, bl);
+  dencode.bencode(PIECE_LENGTH, info.piece_length, bl);
+
+  char info_sha[100] = { 0 };
+  sprintf(info_sha, "%" PRIu64, sha_len);
+  string sha_len_str = info_sha;
+  dencode.bencode_key(PIECES, bl);
+  bl.append(sha_len_str.c_str(), sha_len_str.length());
+  bl.append(':');
+  bl.append(info.sha1_bl.c_str(), sha_len);
+  dencode.bencode_end(bl);
+}
+
+int seed::save_torrent_file()
+{
+  int op_ret = 0;
+  string key = RGW_OBJ_TORRENT;
+  rgw_obj obj(s->bucket, s->object.name);    
+
+  rgw_raw_obj raw_obj;
+  store->obj_to_raw(s->bucket_info.placement_rule, obj, &raw_obj);
+
+  op_ret = store->omap_set(raw_obj, key, bl);
+  if (op_ret < 0)
+  {
+    ldout(s->cct, 0) << "ERROR: failed to omap_set() op_ret = " << op_ret << dendl;
+    return op_ret;
+  }
+
+  return op_ret;
+}