initial code repo
[stor4nfv.git] / src / ceph / src / rgw / rgw_tools.cc
diff --git a/src/ceph/src/rgw/rgw_tools.cc b/src/ceph/src/rgw/rgw_tools.cc
new file mode 100644 (file)
index 0000000..b79fecb
--- /dev/null
@@ -0,0 +1,206 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <errno.h>
+
+#include "common/errno.h"
+#include "common/safe_io.h"
+
+#include "include/types.h"
+
+#include "rgw_common.h"
+#include "rgw_rados.h"
+#include "rgw_tools.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+#define READ_CHUNK_LEN (512 * 1024)
+
+static std::map<std::string, std::string>* ext_mime_map;
+
+int rgw_put_system_obj(RGWRados *rgwstore, const rgw_pool& pool, const string& oid, const char *data, size_t size, bool exclusive,
+                       RGWObjVersionTracker *objv_tracker, real_time set_mtime, map<string, bufferlist> *pattrs)
+{
+  map<string,bufferlist> no_attrs;
+  if (!pattrs)
+    pattrs = &no_attrs;
+
+  rgw_raw_obj obj(pool, oid);
+
+  int ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv_tracker, set_mtime);
+
+  if (ret == -ENOENT) {
+    ret = rgwstore->create_pool(pool);
+    if (ret >= 0)
+      ret = rgwstore->put_system_obj(NULL, obj, data, size, exclusive, NULL, *pattrs, objv_tracker, set_mtime);
+  }
+
+  return ret;
+}
+
+int rgw_get_system_obj(RGWRados *rgwstore, RGWObjectCtx& obj_ctx, const rgw_pool& pool, const string& key, bufferlist& bl,
+                       RGWObjVersionTracker *objv_tracker, real_time *pmtime, map<string, bufferlist> *pattrs,
+                       rgw_cache_entry_info *cache_info)
+{
+  bufferlist::iterator iter;
+  int request_len = READ_CHUNK_LEN;
+  rgw_raw_obj obj(pool, key);
+
+  obj_version original_readv;
+  if (objv_tracker && !objv_tracker->read_version.empty()) {
+    original_readv = objv_tracker->read_version;
+  }
+
+  do {
+    RGWRados::SystemObject source(rgwstore, obj_ctx, obj);
+    RGWRados::SystemObject::Read rop(&source);
+
+    rop.stat_params.attrs = pattrs;
+    rop.stat_params.lastmod = pmtime;
+
+    int ret = rop.stat(objv_tracker);
+    if (ret < 0)
+      return ret;
+
+    rop.read_params.cache_info = cache_info;
+
+    ret = rop.read(0, request_len - 1, bl, objv_tracker);
+    if (ret == -ECANCELED) {
+      /* raced, restart */
+      if (!original_readv.empty()) {
+        /* we were asked to read a specific obj_version, failed */
+        return ret;
+      }
+      if (objv_tracker) {
+        objv_tracker->read_version.clear();
+      }
+      source.invalidate_state();
+      continue;
+    }
+    if (ret < 0)
+      return ret;
+
+    if (ret < request_len)
+      break;
+    bl.clear();
+    request_len *= 2;
+  } while (true);
+
+  return 0;
+}
+
+int rgw_delete_system_obj(RGWRados *rgwstore, const rgw_pool& pool, const string& oid,
+                          RGWObjVersionTracker *objv_tracker)
+{
+  rgw_raw_obj obj(pool, oid);
+  return rgwstore->delete_system_obj(obj, objv_tracker);
+}
+
+void parse_mime_map_line(const char *start, const char *end)
+{
+  char line[end - start + 1];
+  strncpy(line, start, end - start);
+  line[end - start] = '\0';
+  char *l = line;
+#define DELIMS " \t\n\r"
+
+  while (isspace(*l))
+    l++;
+
+  char *mime = strsep(&l, DELIMS);
+  if (!mime)
+    return;
+
+  char *ext;
+  do {
+    ext = strsep(&l, DELIMS);
+    if (ext && *ext) {
+      (*ext_mime_map)[ext] = mime;
+    }
+  } while (ext);
+}
+
+
+void parse_mime_map(const char *buf)
+{
+  const char *start = buf, *end = buf;
+  while (*end) {
+    while (*end && *end != '\n') {
+      end++;
+    }
+    parse_mime_map_line(start, end);
+    end++;
+    start = end;
+  }
+}
+
+static int ext_mime_map_init(CephContext *cct, const char *ext_map)
+{
+  int fd = open(ext_map, O_RDONLY);
+  char *buf = NULL;
+  int ret;
+  if (fd < 0) {
+    ret = -errno;
+    ldout(cct, 0) << __func__ << " failed to open file=" << ext_map
+                  << " : " << cpp_strerror(-ret) << dendl;
+    return ret;
+  }
+
+  struct stat st;
+  ret = fstat(fd, &st);
+  if (ret < 0) {
+    ret = -errno;
+    ldout(cct, 0) << __func__ << " failed to stat file=" << ext_map
+                  << " : " << cpp_strerror(-ret) << dendl;
+    goto done;
+  }
+
+  buf = (char *)malloc(st.st_size + 1);
+  if (!buf) {
+    ret = -ENOMEM;
+    ldout(cct, 0) << __func__ << " failed to allocate buf" << dendl;
+    goto done;
+  }
+
+  ret = safe_read(fd, buf, st.st_size + 1);
+  if (ret != st.st_size) {
+    // huh? file size has changed?
+    ldout(cct, 0) << __func__ << " raced! will retry.." << dendl;
+    free(buf);
+    close(fd);
+    return ext_mime_map_init(cct, ext_map);
+  }
+  buf[st.st_size] = '\0';
+
+  parse_mime_map(buf);
+  ret = 0;
+done:
+  free(buf);
+  close(fd);
+  return ret;
+}
+
+const char *rgw_find_mime_by_ext(string& ext)
+{
+  map<string, string>::iterator iter = ext_mime_map->find(ext);
+  if (iter == ext_mime_map->end())
+    return NULL;
+
+  return iter->second.c_str();
+}
+
+int rgw_tools_init(CephContext *cct)
+{
+  ext_mime_map = new std::map<std::string, std::string>;
+  int ret = ext_mime_map_init(cct, cct->_conf->rgw_mime_types_file.c_str());
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
+void rgw_tools_cleanup()
+{
+  delete ext_mime_map;
+  ext_mime_map = nullptr;
+}