]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: introduce libradosgw
authorOrit Wasserman <owasserm@redhat.com>
Tue, 12 May 2015 10:12:03 +0000 (12:12 +0200)
committerMatt Benjamin <mbenjamin@redhat.com>
Fri, 12 Feb 2016 16:55:55 +0000 (11:55 -0500)
This change exposes the radosgw service as a dynamic
library, and also introduces a file-oriented view of the
RGW corpus as a namespace (e.g., for interop with NFS
clients).

The change concatenates the following commits:
    * rgw: add rgw_file.h
    * rgw: add RGWLibRequest, RGWLibFrontend and RGWLibProcess
    * rgw: Add user command interface for librgw
    *     user_commands
    *     Implement gen_request
    *    Install librgw.a
    *     add rgw_request.cc to Makefile.am
    *    Add empty API to librgw.h
    *    Add rgw_file.cc
    *    Make RGWLib a global object
    *    Implement lookup and readdir - wip
    *    Add rgw_rest_lib.cc
    *    Install rgw_file.h
    *    wip implement mount
    *      RGWLibIO

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
13 files changed:
src/CMakeLists.txt
src/include/Makefile.am
src/include/rados/librgw.h
src/include/rados/rgw_file.h [new file with mode: 0644]
src/rgw/Makefile.am
src/rgw/librgw.cc
src/rgw/rgw_common.h
src/rgw/rgw_file.cc [new file with mode: 0644]
src/rgw/rgw_lib.h [new file with mode: 0644]
src/rgw/rgw_rest_lib.cc [new file with mode: 0644]
src/rgw/rgw_rest_lib.h [new file with mode: 0644]
src/rgw/rgw_user.cc
src/rgw/rgw_user.h

index 39f77a3934f35f56981a59201b85af14e78a1def..da67ad80e344a397ac25a0f8cef74524397576af 100644 (file)
@@ -1170,11 +1170,15 @@ if(${WITH_RADOSGW})
     rgw/rgw_request.cc
     rgw/rgw_process.cc
     rgw/rgw_frontend.cc
+    rgw/rgw_rest_lib.cc
     rgw/rgw_object_expirer_core.cc
     rgw/rgw_website.cc
-    rgw/rgw_xml_enc.cc)
+    rgw/rgw_xml_enc.cc
+    )
 
   add_library(rgw_a STATIC ${rgw_a_srcs})
+  set_target_properties(rgw_a PROPERTIES OUTPUT_NAME rgw)
+  install(TARGETS rgw_a DESTINATION lib)
 
   include_directories("${CMAKE_SOURCE_DIR}/src/civetweb/include")
 
index 900a4c11338373ce073359a487d4e512b80b6d97..1224c1ea1138ccbeba5a7ee2aa2a83650f894ae0 100644 (file)
@@ -14,6 +14,11 @@ rados_include_DATA = \
        $(srcdir)/include/crc32c.h \
        $(srcdir)/include/memory.h
 
+if WITH_RADOSGW
+rados_include_DATA += \
+       $(srcdir)/include/rados/librgw.h \
+       $(srcdir)/include/rados/rgw_file.h
+endif # WITH_RADOSGW
 
 if WITH_RBD
 librbd_includedir = $(includedir)/rbd
@@ -110,6 +115,7 @@ noinst_HEADERS += \
        include/rados/crc32c.h \
        include/rados/buffer.h \
        include/rados/buffer_fwd.h \
+       include/rados/rgw_file.h \
        include/radosstriper/libradosstriper.h \
        include/radosstriper/libradosstriper.hpp \
        include/rbd/features.h \
index cc2d6bdfd32c5ba17f6fe857dae0e4ea35ae58d1..f48b5eb23dcfbedaca518cdcc2b125fb0a16c11a 100644 (file)
@@ -28,6 +28,33 @@ int librgw_acl_xml2bin(librgw_t rgw, const char *xml, char **bin, int *bin_len);
 void librgw_free_bin(librgw_t rgw, char *bin);
 void librgw_shutdown(librgw_t rgw);
 
+/* librgw external interface */
+int librgw_init();
+int librgw_stop();
+
+/* User interface */
+int get_userinfo_by_uid(const string& uid);
+int get_user_acl();
+int set_user_permissions();
+int set_user_quota();
+int get_user_quota();
+
+/* buckets */
+int get_user_buckets_list();
+int get_bucket_objects_list();
+int create_bucket();
+int delete_bucket();
+int get_bucket_attributes();
+int set_bucket_attributes();
+
+/* objects */
+int create_object ();
+int delete_object();
+int rgw_write();
+int rgw_read();
+int get_object_attributes();
+int set_object_attributes();
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/include/rados/rgw_file.h b/src/include/rados/rgw_file.h
new file mode 100644 (file)
index 0000000..2c9350b
--- /dev/null
@@ -0,0 +1,104 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * convert RGW commands to file commands
+ *
+ * Copyright (C) 2011 New Dream Network
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+#ifndef RGW_FILE_H
+#define RGW_FILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * dynamic allocated handle to support nfs handle
+ * Currently we support only one instance of librgw.
+ * In order to support several instance we will need to include an
+ * instance id (16bit)
+ */
+struct nfs_handle
+{
+  uint64_t handle;
+};
+
+/*
+  get entity handle
+*/
+int rgw_get_handle(const char *uri, struct nfs_handle *handle);
+
+/*
+  check handle
+*/
+int rgw_check_handle(const struct nfs_handle *handle);
+
+  int rgw_mount(const char *uid, const char *key, const char *secret,
+                         const struct nfs_handle *handle);
+
+/*
+  create a new dirctory
+*/
+int rgw_create_directory(const struct nfs_handle *parent_handle, const char *name);
+
+/*
+  create a new file
+*/
+  int rgw_create_file(const struct nfs_handle *parent_handle, const char* name);
+
+  int rgw_rename(const struct nfs_handle *parent_handle, const char* old_name, const char* new_name);
+
+/*
+  remove file or directory
+*/
+int rgw_unlink(const struct nfs_handle *parent_handle, const char* path);
+
+/*
+    lookup a directory or file
+*/
+int rgw_lookup(const struct nfs_handle *parent_handle, const char *path, uint64_t *handle);
+
+/*
+    read  directory content
+*/
+int rgw_readdir(const struct nfs_handle *parent_handle, const char *path);
+
+int rgw_set_attributes(const struct nfs_handle *handle);
+
+int rgw_get_attributes(const struct nfs_handle *handle);
+
+int rgw_open(const struct nfs_handle *handle);
+
+int rgw_close(const struct nfs_handle *handle);
+
+int read(const struct nfs_handle *handle);
+
+int write(const struct nfs_handle *handle);
+
+int set_user_permissions(cosnt char *uid);
+
+int get_user_permissions(const char *uid);
+
+int set_dir_permissions(const struct nfs_handle *handle);
+
+int get_dir_permissions(const struct nfs_handle *handle);
+
+int set_file_permissions(const struct nfs_handle *handle);
+
+int get_file_permissions(const struct nfs_handle *handle);
+
+int acl2perm();
+
+int perm2acl();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
index d2bb9ac0e4944edda400260d5c6c190c59e1e629..494483b2974963bd59a95f92cdca199761da8c8f 100644 (file)
@@ -105,6 +105,7 @@ radosgw_SOURCES = \
        rgw/rgw_swift.cc \
        rgw/rgw_swift_auth.cc \
        rgw/rgw_loadgen.cc \
+       rgw/rgw_rest_lib.cc \
        rgw/rgw_main.cc
 radosgw_CFLAGS = -I$(srcdir)/civetweb/include
 radosgw_LDADD = $(LIBRGW) $(LIBCIVETWEB) $(LIBRGW_DEPS) $(RESOLV_LIBS) $(CEPH_GLOBAL)
index f9b39aeba59e217b7286c66e465c542eb7770e86..a8dc95ecdb52b25517526403238814ab787f2c5d 100644 (file)
  * Foundation.  See file COPYING.
  *
  */
+#include <sys/types.h>
+#include <string.h>
 
 #include "include/types.h"
 #include "include/rados/librgw.h"
 #include "rgw/rgw_acl_s3.h"
 #include "rgw_acl.h"
+
+#include "include/str_list.h"
+#include "global/global_init.h"
+#include "common/config.h"
+#include "common/errno.h"
+#include "common/Timer.h"
+#include "common/Throttle.h"
+#include "common/WorkQueue.h"
 #include "common/ceph_argparse.h"
 #include "common/ceph_context.h"
 #include "common/common_init.h"
 #include "common/dout.h"
 
+#include "rgw_rados.h"
+#include "rgw_resolve.h"
+#include "rgw_op.h"
+#include "rgw_rest.h"
+#include "rgw_frontend.h"
+#include "rgw_request.h"
+#include "rgw_process.h"
+#include "rgw_rest_user.h"
+#include "rgw_rest_s3.h"
+#include "rgw_rest_lib.h"
+#include "rgw_auth_s3.h"
+#include "rgw_lib.h"
+
 #include <errno.h>
 #include <sstream>
 #include <string.h>
@@ -133,3 +156,434 @@ void librgw_shutdown(librgw_t rgw)
 {
   rgw->put();
 }
+
+class C_InitTimeout : public Context {
+public:
+  C_InitTimeout() {}
+  void finish(int r) {
+    derr << "Initialization timeout, failed to initialize" << dendl;
+    exit(1);
+  }
+};
+
+struct RGWLibRequest : public RGWRequest {
+  string method;
+  string resource;
+  int content_length;
+  atomic_t *fail_flag;
+
+  RGWLibRequest(uint64_t req_id, const string& _m, const  string& _r, int _cl, bool user_command,
+               atomic_t *_ff) :  RGWRequest(req_id), method(_m), resource(_r), content_length(_cl), fail_flag(_ff)
+  {
+     s->librgw_user_command =  user_command;
+  }
+};
+
+void RGWLibRequestEnv::set_date(utime_t& tm)
+{
+  stringstream s;
+  tm.asctime(s);
+  date_str = s.str();
+}
+
+int RGWLibRequestEnv::sign(RGWAccessKey& access_key)
+{
+  map<string, string> meta_map;
+  map<string, string> sub_resources;
+
+  string canonical_header;
+  string digest;
+
+  rgw_create_s3_canonical_header(request_method.c_str(),
+                                 NULL, /* const char *content_md5 */
+                                 content_type.c_str(),
+                                 date_str.c_str(),
+                                 meta_map,
+                                 uri.c_str(),
+                                 sub_resources,
+                                 canonical_header);
+
+  int ret = rgw_get_s3_header_digest(canonical_header, access_key.key, digest);
+  if (ret < 0) {
+    return ret;
+  }
+
+};
+
+class RGWLibFrontend : public RGWProcessFrontend {
+public:
+  RGWLibFrontend(RGWProcessEnv& pe, RGWFrontendConfig *_conf) : RGWProcessFrontend(pe, _conf) {}
+  int init();
+  void gen_request(const string& method, const string& resource, int content_length, bool user_command,
+                  atomic_t *fail_flag);
+};
+
+class RGWLibProcess : public RGWProcess {
+    RGWAccessKey access_key;
+public:
+  RGWLibProcess(CephContext *cct, RGWProcessEnv *pe, int num_threads, RGWFrontendConfig *_conf) :
+    RGWProcess(cct, pe, num_threads, _conf) {}
+  void run();
+  void checkpoint();
+  void handle_request(RGWRequest *req);
+  void gen_request(const string& method, const string& resource, int content_length, bool user_command,
+                  atomic_t *fail_flag);
+  void set_access_key(RGWAccessKey& key) { access_key = key; }
+};
+
+
+void RGWLibProcess::checkpoint()
+{
+    m_tp.drain(&req_wq);
+}
+
+void RGWLibProcess::run()
+{
+}
+
+void RGWLibProcess::gen_request(const string& method, const string& resource, int content_length,
+                               bool user_command, atomic_t *fail_flag)
+{
+  RGWLibRequest *req = new RGWLibRequest(store->get_new_req_id(), method, resource,
+                                        content_length, user_command, fail_flag);
+  dout(10) << "allocated request req=" << hex << req << dec << dendl;
+  req_throttle.get(1);
+  req_wq.queue(req);
+}
+
+void RGWLibProcess::handle_request(RGWRequest *r)
+{
+  RGWLibRequest *req = static_cast<RGWLibRequest *>(r);
+
+  RGWLibRequestEnv env;
+
+  utime_t tm = ceph_clock_now(NULL);
+
+  env.port = 80;
+  env.content_length = req->content_length;
+  env.content_type = "binary/octet-stream"; /* TBD */
+  env.request_method = req->method;
+  env.uri = req->resource;
+  env.set_date(tm);
+  env.sign(access_key);
+
+  RGWLibIO client_io(&env);
+
+  int ret = process_request(store, rest, req, &client_io, olog);
+  if (ret < 0) {
+    /* we don't really care about return code */
+    dout(20) << "process_request() returned " << ret << dendl;
+
+  }
+    delete req;
+}
+
+void RGWLibFrontend::gen_request(const string& method, const string& resource, int content_length,
+                                bool user_command, atomic_t *fail_flag)
+{
+     RGWLibProcess *lib_process = static_cast<RGWLibProcess *>(pprocess);
+     lib_process->gen_request(method, resource, content_length, user_command, fail_flag);
+}
+
+int RGWLib::init()
+{
+  int r = 0;
+  /* alternative default for module */
+  vector<const char *> def_args;
+  def_args.push_back("--debug-rgw=1/5");
+  def_args.push_back("--keyring=$rgw_data/keyring");
+  def_args.push_back("--log-file=/var/log/radosgw/$cluster-$name.log");
+
+  vector<const char*> args;
+  global_init(&def_args, args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_DAEMON,
+             CINIT_FLAG_UNPRIVILEGED_DAEMON_DEFAULTS);
+
+  Mutex mutex("main");
+  SafeTimer init_timer(g_ceph_context, mutex);
+  init_timer.init();
+  mutex.Lock();
+  init_timer.add_event_after(g_conf->rgw_init_timeout, new C_InitTimeout);
+  mutex.Unlock();
+
+  common_init_finish(g_ceph_context);
+
+  rgw_tools_init(g_ceph_context);
+
+  rgw_init_resolver();
+
+  store = RGWStoreManager::get_storage(g_ceph_context,
+      g_conf->rgw_enable_gc_threads, g_conf->rgw_enable_quota_threads);
+
+  if (!store) {
+    mutex.Lock();
+    init_timer.cancel_all_events();
+    init_timer.shutdown();
+    mutex.Unlock();
+
+    derr << "Couldn't init storage provider (RADOS)" << dendl;
+    return EIO;
+  }
+
+  r = rgw_perf_start(g_ceph_context);
+
+  rgw_rest_init(g_ceph_context, store->region);
+
+  mutex.Lock();
+  init_timer.cancel_all_events();
+  init_timer.shutdown();
+  mutex.Unlock();
+
+  if (r)
+    return 1;
+
+  rgw_user_init(store);
+  rgw_bucket_init(store->meta_mgr);
+  rgw_log_usage_init(g_ceph_context, store);
+
+
+  mgr = new RGWRESTMgr_Lib();
+  mgr->set_logging(true);
+  rest.register_default_mgr(mgr);
+
+  if (!g_conf->rgw_ops_log_socket_path.empty()) {
+    olog = new OpsLogSocket(g_ceph_context, g_conf->rgw_ops_log_data_backlog);
+    olog->init(g_conf->rgw_ops_log_socket_path);
+  }
+
+  int port = 80;
+  RGWProcessEnv env = { store, &rest, olog, port };
+
+  fec = new RGWFrontendConfig("librgw");
+  fe = new RGWLibFrontend(env, fec);
+
+  fe->init();
+  if (r < 0) {
+    derr << "ERROR: failed initializing frontend" << dendl;
+    return -r;
+  }
+
+  fe->run();
+
+  return 0;
+
+}
+
+int RGWLib::stop()
+{
+  derr << "shutting down" << dendl;
+
+  fe->stop();
+
+  fe->join();
+
+  delete fe;
+
+  rgw_log_usage_finalize();
+
+  delete olog;
+
+  RGWStoreManager::close_storage(store);
+
+  rgw_tools_cleanup();
+  rgw_shutdown_resolver();
+
+  rgw_perf_stop(g_ceph_context);
+
+  dout(1) << "final shutdown" << dendl;
+  g_ceph_context->put();
+
+  ceph::crypto::shutdown();
+
+  return 0;
+}
+
+int RGWLib::get_uri(const uint64_t handle, string &uri)
+{
+  ceph::unordered_map<uint64_t, string>::iterator i = handles_map.find(handle);
+  if (i != handles_map.end()) {
+    uri =  i->second;
+    return 0;
+  }
+  return -1;
+}
+
+uint64_t RGWLib::get_new_handle(const string& uri)
+{
+  ceph::unordered_map<string, uint64_t>::iterator i = allocated_objects_handles.find(uri);
+  if (i != allocated_objects_handles.end()) {
+    return i->second;
+  }
+
+  allocated_objects_handles[uri] = last_allocated_handle.inc();
+  handles_map[last_allocated_handle.read()] = uri;
+
+  return last_allocated_handle.read();
+}
+
+int RGWLibIO::set_uid(RGWRados *store, const rgw_user& uid)
+{
+  int ret = rgw_get_user_info_by_uid(store, uid, user_info, NULL);
+  if (ret < 0) {
+    derr << "ERROR: failed reading user info: uid=" << uid << " ret="
+        << ret << dendl;
+  }
+  return ret;
+}
+
+int RGWLibIO::write_data(const char *buf, int len)
+{
+  return len;
+}
+
+int RGWLibIO::read_data(char *buf, int len)
+{
+  int read_len = MIN(left_to_read, (uint64_t)len);
+  left_to_read -= read_len;
+  return read_len;
+}
+
+void RGWLibIO::flush()
+{
+}
+
+int RGWLibIO::complete_request()
+{
+  return 0;
+}
+
+void RGWLibIO::init_env(CephContext *cct)
+{
+  env.init(cct);
+
+  left_to_read = re->content_length;
+
+  char buf[32];
+  snprintf(buf, sizeof(buf), "%lld", (long long)re->content_length);
+  env.set("CONTENT_LENGTH", buf);
+
+  env.set("CONTENT_TYPE", re->content_type.c_str());
+  env.set("HTTP_DATE", re->date_str.c_str());
+
+  for (map<string, string>::iterator iter = re->headers.begin(); iter != re->headers.end(); ++iter) {
+    env.set(iter->first.c_str(), iter->second.c_str());
+  }
+
+  env.set("REQUEST_METHOD", re->request_method.c_str());
+  env.set("REQUEST_URI", re->uri.c_str());
+  env.set("QUERY_STRING", re->query_string.c_str());
+  env.set("SCRIPT_URI", re->uri.c_str());
+
+  char port_buf[16];
+  snprintf(port_buf, sizeof(port_buf), "%d", re->port);
+  env.set("SERVER_PORT", port_buf);
+}
+
+int RGWLibIO::send_status(int status, const char *status_name)
+{
+  return 0;
+}
+
+int RGWLibIO::send_100_continue()
+{
+  return 0;
+}
+
+int RGWLibIO::complete_header()
+{
+  return 0;
+}
+
+int RGWLibIO::send_content_length(uint64_t len)
+{
+  return 0;
+}
+
+int RGWLib::get_userinfo_by_uid(const string& uid, RGWUserInfo &info)
+{
+  atomic_t failed;
+
+  fe->gen_request("GET", uid, 4096, true, &failed);
+  return failed.read();
+}
+
+int RGWLib::get_user_acl()
+{
+}
+
+int RGWLib::set_user_permissions()
+{
+}
+
+int RGWLib::set_user_quota()
+{
+}
+
+int RGWLib::get_user_quota()
+{
+}
+
+int RGWLib::get_user_buckets_list()
+{
+  /* need to authanitcate first */
+  atomic_t failed;
+  fe->gen_request("GET", "", 4096, false, &failed);
+  return failed.read();
+
+}
+
+int RGWLib::get_bucket_objects_list()
+{
+}
+
+int RGWLib::create_bucket()
+{
+}
+
+int RGWLib::delete_bucket()
+{
+}
+
+int RGWLib::get_bucket_attributes()
+{
+}
+
+int RGWLib::set_bucket_attributes()
+{
+}
+
+int RGWLib::create_object ()
+{
+}
+
+int RGWLib::delete_object()
+{
+}
+
+int RGWLib::write()
+{
+}
+
+int RGWLib::read()
+{
+}
+
+int RGWLib::get_object_attributes()
+{
+}
+
+int RGWLib::set_object_attributes()
+{
+}
+
+/* global RGW library object */
+static RGWLib rgwlib;
+
+int librgw_init()
+{
+  return rgwlib.init();
+}
+
+int librgw_stop()
+{
+  return rgwlib.stop();
+}
index e444f735c4425f156f49c27248df631f1551aad0..f9823397a73310a3ad7125ee8aad34d0d514fa8f 100644 (file)
@@ -1146,6 +1146,8 @@ struct req_state {
    req_info info;
    req_init_state init_state;
 
+   bool librgw_user_command;
+
    req_state(CephContext *_cct, class RGWEnv *e);
    ~req_state();
 };
diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc
new file mode 100644 (file)
index 0000000..0c8e787
--- /dev/null
@@ -0,0 +1,145 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include "rgw_file.h"
+
+extern RGWLib librgw;
+
+
+bool is_root(const string& uri)
+{
+  return uri.equals("");
+}
+
+bool is_bucket(const string& uri)
+{
+  int pos = req.find('/');
+  return (pos < 0);
+}
+
+/*
+  get generate nfs_handle
+*/
+int rgw_get_handle(const char *uri, struct nfs_handle *handle)
+{
+  handle->handle = librgw.get_handle(uri);
+  return 0;
+}
+
+/*
+  check nfs_handle
+*/
+int rgw_check_handle(const struct nfs_handle *handle)
+{
+  return librgw.check_handle(handle);
+}
+
+int rgw_mount(const char *uid, const char *key, const char *secret,
+                       const struct nfs_handle *handle)
+{
+  int rc;
+  string uri = uid + "\";
+  string auth_hdr;
+  map<string, string> meta_map;
+  map<string, string> sub_resources;
+
+  rgw_create_s3_canonical_header('GET',
+                                 NULL, /* const char *content_md5 */
+                                 'text/html',
+                                 "",
+                                 meta_map,
+                                 urti.c_str(),
+                                 sub_resources,
+                                 auth_hdr);
+
+  /* check key */
+  rc = rgw_get_s3_header_digest(auth_hdr, key, secret);
+  if (rc < 0 ) {
+    return rc;
+  }
+
+  return rgw_get_handle(uri);
+}
+
+/*
+  create a new dirctory
+*/
+int rgw_create_directory(const struct nfs_handle *parent_handle, const char *name)
+{
+  return 0;
+}
+
+/*
+  create a new file
+*/
+int rgw_create_file(const struct nfs_handle *parent_handle, const char* name)
+{
+  return 0;
+}
+
+int rgw_rename(const struct nfs_handle *parent_handle, const char* old_name, const char* new_name)
+{
+  return 0;
+}
+/*
+  remove file or directory
+*/
+int rgw_unlink(const struct nfs_handle *parent_handle, const char* path)
+{
+  return 0;
+}
+
+/*
+    lookup a directory or file
+*/
+int rgw_lookup(const struct nfs_handle *parent_handle, const struct nfs_handle *parent_handle,
+              const char *path, uint64_t *handle)
+{
+  string uri;
+  int rc;
+
+  rc = get_uri(parent_handle, uri);
+  if (rc < 0 ) { /* invalid parent */
+    return rc;
+  }
+
+  if (is_root(uri)) {
+    librgw.get_bucket(uri);
+  } else if (is_bucket(uri)) {
+    /* get the object */
+  } else { /* parent cannot be an object */
+    return -1;
+  }
+
+  uri += "/" + path;
+  /* find or create an handle for the object or bucket */
+  *handle =  librgw.get_new_handle(uri);
+  return 0;
+}
+
+/*
+  read directory content
+*/
+int rgw_readdir(const struct nfs_handle *parent_handle, const char *path)
+{
+  string uri;
+  int rc;
+
+  rc = get_uri(parent_handle, uri);
+  if (rc < 0 ) { /* invalid parent */
+    return rc;
+  }
+
+  if (librgw.is_root(uri)) {
+    /* get the bucket list */
+    return librgw.get_user_buckets_list();
+  } else if (librgw.is_bucket(uri)) {
+    /* get the object list */
+    return librgw.get_buckets_object_list();
+  } else { /* parent cannot be an object */
+    return -1;    
+  }
+
+  return 0;
+}
+
+
diff --git a/src/rgw/rgw_lib.h b/src/rgw/rgw_lib.h
new file mode 100644 (file)
index 0000000..29b7015
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef RGW_LIB_H
+#define RGW_LIB_H
+
+#include "include/unordered_map.h"
+#include "rgw_common.h"
+#include "rgw_client_io.h"
+#include "rgw_rest.h"
+#include "rgw_request.h"
+#include "rgw_process.h"
+
+
+class RGWLibFrontendConfig;
+class RGWLibFrontend;
+class OpsLogSocket;
+class RGWREST;
+class RGWRESTMgr;
+
+class RGWLib {
+  RGWFrontendConfig *fec;
+  RGWLibFrontend *fe;
+  OpsLogSocket *olog;
+  RGWREST rest;
+  RGWProcessEnv env;
+  RGWRados *store;
+  RGWRESTMgr *mgr;
+  ceph::unordered_map<string, uint64_t> allocated_objects_handles;
+  ceph::unordered_map<uint64_t, string> handles_map;
+  atomic64_t last_allocated_handle;
+public:
+  RGWLib() {}
+  ~RGWLib() {}
+
+  int init();
+  int stop();
+
+  /* generate dynamic handle currently unique per librgw object
+   */
+  uint64_t get_new_handle(const string& url);
+
+  int get_uri(const uint64_t handle, string &uri);
+
+  /* User interface */
+  int get_userinfo_by_uid(const string& uid, RGWUserInfo &info);
+  int get_user_acl();
+  int set_user_permissions();
+  int set_user_quota();
+  int get_user_quota();
+
+  /* buckets */
+  int get_user_buckets_list();
+  int get_bucket_objects_list();
+  int create_bucket();
+  int delete_bucket();
+  int get_bucket_attributes();
+  int set_bucket_attributes();
+
+  /* objects */
+  int create_object ();
+  int delete_object();
+  int write();
+  int read();
+  int get_object_attributes();
+  int set_object_attributes();
+};
+
+/* request interface */
+
+struct RGWLibRequestEnv {
+  int port;
+  uint64_t content_length;
+  string content_type;
+  string request_method;
+  string uri;
+  string query_string;
+  string date_str;
+
+  map<string, string> headers;
+
+  RGWLibRequestEnv() : port(0), content_length(0) {}
+
+  void set_date(utime_t& tm);
+  int sign(RGWAccessKey& access_key);
+};
+
+class RGWLibIO : public RGWClientIO
+{
+  uint64_t left_to_read;
+  RGWLibRequestEnv *re;
+  RGWUserInfo user_info;
+public:
+  RGWLibIO(RGWLibRequestEnv *_re): re(_re) {}
+  RGWLibIO(RGWLibRequestEnv *_re, const RGWUserInfo &_user_info)
+         : re(_re), user_info(_user_info) {}
+
+  void init_env(CephContext *cct);
+
+  int set_uid(RGWRados* store, const rgw_user& uid);
+  const RGWUserInfo &get_user() { return user_info; }
+  int write_data(const char *buf, int len);
+  int read_data(char *buf, int len);
+
+  int send_status(int status, const char *status_name);
+  int send_100_continue();
+  int complete_header();
+  int complete_request();
+  int send_content_length(uint64_t len);
+
+  void flush();
+};
+
+#endif
diff --git a/src/rgw/rgw_rest_lib.cc b/src/rgw/rgw_rest_lib.cc
new file mode 100644 (file)
index 0000000..8ce6543
--- /dev/null
@@ -0,0 +1,16 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#include "rgw_rest.h"
+#include "rgw_rest_s3.h"
+#include "rgw_rest_user.h"
+#include "rgw_rest_lib.h"
+
+
+RGWHandler *RGWRESTMgr_Lib::get_handler(struct req_state *s)
+{
+  if (!s->librgw_user_command) {
+    return new RGWHandler_ObjStore_Lib;
+  }
+
+  return RGWRESTMgr_S3::get_handler(s);
+}
diff --git a/src/rgw/rgw_rest_lib.h b/src/rgw/rgw_rest_lib.h
new file mode 100644 (file)
index 0000000..222a73f
--- /dev/null
@@ -0,0 +1,21 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_RGW_REST_LIB_H
+#define CEPH_RGW_REST_LIB_H
+
+class RGWRESTMgr_Lib : public RGWRESTMgr_S3 {
+public:
+  RGWRESTMgr_Lib() {}
+  virtual ~RGWRESTMgr_Lib() {}
+  virtual RGWHandler *get_handler(struct req_state *s);
+};
+
+class RGWHandler_ObjStore_Lib : public RGWHandler_User {
+  friend class RGWRestMgr_Lib;
+public:
+  RGWHandler_ObjStore_Lib() {}
+  virtual ~RGWHandler_ObjStore_Lib() {}
+};
+
+#endif
index fb313d0071b48885d18c6dbdcbecc021898de839..cd27721f03c56539a3b7652d97889a9a16733bdb 100644 (file)
@@ -279,7 +279,7 @@ int rgw_get_user_info_from_index(RGWRados *store, string& key, rgw_bucket& bucke
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
 int rgw_get_user_info_by_uid(RGWRados *store,
-                             rgw_user& uid,
+                             const rgw_user& uid,
                              RGWUserInfo& info,
                              RGWObjVersionTracker *objv_tracker,
                              time_t *pmtime,
index bff4a52912e8172eefde432a5d056716bdf9c338..2a41ac05a39e3fb044eeaf3614b48f766c065acc 100644 (file)
@@ -82,7 +82,7 @@ extern int rgw_store_user_attrs(RGWRados *store,
  * returns: 0 on success, -ERR# on failure (including nonexistence)
  */
 extern int rgw_get_user_info_by_uid(RGWRados *store,
-                                    rgw_user& user_id,
+                                    const rgw_user& user_id,
                                     RGWUserInfo& info,
                                     RGWObjVersionTracker *objv_tracker = NULL,
                                     time_t *pmtime                     = NULL,