]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librgw: rgw_file_handle refactor, plus get/put
authorMatt Benjamin <mbenjamin@redhat.com>
Sun, 25 Oct 2015 21:22:43 +0000 (17:22 -0400)
committerMatt Benjamin <mbenjamin@redhat.com>
Fri, 12 Feb 2016 17:05:02 +0000 (12:05 -0500)
Implement encapsulation of RGWFileHandle in rgw_file_handle,
so return these from rgw_lookup(), add new rgw_fh_rele() to release
internal state.

Currently the rgw_fh_rele just deletes, in future might be extended
with refcnt support.

Implement the first (atomic) stage of i/o using GET and PUT, add a
new librgw_file_gp test driver for this.

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
src/include/rados/rgw_file.h
src/rgw/rgw_file.cc
src/rgw/rgw_file.h
src/rgw/rgw_os_lib.h
src/rgw/rgw_rados.h
src/test/CMakeLists.txt
src/test/librgw_file.cc
src/test/librgw_file_gp.cc [new file with mode: 0644]

index 512b165f5ab07206bafeaae152f6e8505ea1b01f..b8c7883153884b8b6b1ef755e1d4f34ccfd93073 100644 (file)
@@ -130,14 +130,20 @@ int rgw_rename(struct rgw_fs *rgw_fs,
   remove file or directory
 */
 int rgw_unlink(struct rgw_fs *rgw_fs,
-              const struct rgw_file_handle *parent_handle, const char* path);
+              const struct rgw_file_handle *parent_fh, const char* path);
 
 /*
   lookup a directory or file
 */
 int rgw_lookup(struct rgw_fs *rgw_fs,
-              const struct rgw_file_handle *parent_handle, const char *path,
-              struct rgw_file_handle *handle);
+             const struct rgw_file_handle *parent_fh, const char *path,
+             struct rgw_file_handle **fh, uint32_t flags);
+
+/*
+ * release file handle
+ */
+int rgw_fh_rele(struct rgw_fs *rgw_fs, struct rgw_file_handle *fh,
+               uint32_t flags);
 
 /*
   read  directory content
@@ -145,7 +151,7 @@ int rgw_lookup(struct rgw_fs *rgw_fs,
 typedef bool (*rgw_readdir_cb)(const char *name, void *arg, uint64_t offset);
 
 int rgw_readdir(struct rgw_fs *rgw_fs,
-               const struct rgw_file_handle *parent_handle, uint64_t *offset,
+               const struct rgw_file_handle *parent_fh, uint64_t *offset,
                rgw_readdir_cb rcb, void *cb_arg, bool *eof);
 
 /* XXX (get|set)attr mask bits */
@@ -161,51 +167,67 @@ int rgw_readdir(struct rgw_fs *rgw_fs,
    get unix attributes for object
 */
 int rgw_getattr(struct rgw_fs *rgw_fs,
-               const struct rgw_file_handle *handle, struct stat *st);
+               struct rgw_file_handle *handle, struct stat *st);
 
 /*
    set unix attributes for object
 */
 int rgw_setattr(struct rgw_fs *rgw_fs,
-               const struct rgw_file_handle *handle, struct stat *st,
+               struct rgw_file_handle *handle, struct stat *st,
                uint32_t mask);
 
 /*
    truncate file
 */
 int rgw_truncate(struct rgw_fs *rgw_fs,
-                const struct rgw_file_handle *handle, uint64_t size);
+                struct rgw_file_handle *handle, uint64_t size);
 
 /*
    open file
 */
-int rgw_open(struct rgw_fs *rgw_fs,
-            const struct rgw_file_handle *handle, uint32_t flags);
+int rgw_open(struct rgw_fs *rgw_fs, struct rgw_file_handle *fh,
+           uint32_t flags);
 
 /*
    close file
 */
-int rgw_close(struct rgw_fs *rgw_fs,
-             const struct rgw_file_handle *handle, uint32_t flags);
+
+#define RGW_CLOSE_FLAG_NONE 0x0000
+#define RGW_CLOSE_FLAG_RELE 0x0001
+
+int rgw_close(struct rgw_fs *rgw_fs, struct rgw_file_handle *fh,
+             uint32_t flags);
 
 /*
    read data from file
 */
 int rgw_read(struct rgw_fs *rgw_fs,
-            const struct rgw_file_handle *handle, uint64_t offset,
+            struct rgw_file_handle *fh, uint64_t offset,
             size_t length, void *buffer);
 
+/* XXX add release fn and UIO type */
+int rgw_readv(struct rgw_fs *rgw_fs,
+             struct rgw_file_handle *fh, uint64_t offset,
+             size_t length, void *buffer);
+
 /*
    write data to file
 */
 int rgw_write(struct rgw_fs *rgw_fs,
-             const struct rgw_file_handle *handle, uint64_t offset,
+             struct rgw_file_handle *fh, uint64_t offset,
+             size_t length, void *buffer);
+
+/* XXX add release fn and UIO type */
+
+int rgw_writev(struct rgw_fs *rgw_fs,
+             const struct rgw_file_handle *fh, uint64_t offset,
              size_t length, void *buffer);
 
+
 /*
    sync written data
 */
-int rgw_fsync(struct rgw_fs *rgw_fs, const struct rgw_file_handle *handle);
+int rgw_fsync(struct rgw_fs *rgw_fs, struct rgw_file_handle *fh);
 
 int set_user_permissions(const char *uid);
 
index 89cfa613c6906ca13b7bcf69f2ee0dc729be5e3c..75fb342f14579077745470882cc31fbfe3f42c44 100644 (file)
@@ -219,13 +219,13 @@ int rgw_unlink(struct rgw_fs *rgw_fs, const struct rgw_file_handle* parent,
   lookup a directory or file
 */
 int rgw_lookup(struct rgw_fs *rgw_fs,
-              const struct rgw_file_handle *parent_handle, const char* path,
-              struct rgw_file_handle *handle)
+             const struct rgw_file_handle *parent_fh, const char* path,
+             struct rgw_file_handle **fh, uint32_t flags)
 {
   string uri;
   int rc;
 
-  rc = librgw.get_uri(parent_handle->handle, uri);
+  rc = librgw.get_uri(parent_fh->handle, uri);
   if (rc < 0 ) { /* invalid parent */
     return rc;
   }
@@ -243,8 +243,25 @@ int rgw_lookup(struct rgw_fs *rgw_fs,
   uri += "/";
   uri += path;
 
+  RGWFileHandle* rgw_fh = new RGWFileHandle();
+  struct rgw_file_handle *rfh = rgw_fh->get_fh();
+
   /* find or create a handle for the object or bucket */
-  handle->handle = librgw.get_handle(uri);
+  rfh->handle = librgw.get_handle(uri);
+  *fh = rfh;
+
+  return 0;
+} /* rgw_lookup */
+
+/*
+ * release file handle
+ */
+int rgw_fh_rele(struct rgw_fs *rgw_fs, struct rgw_file_handle *fh,
+               uint32_t flags)
+{
+  RGWFileHandle* rgw_fh = get_rgwfh(fh);
+  rgw_fh->rele();
+
   return 0;
 }
 
@@ -252,12 +269,12 @@ int rgw_lookup(struct rgw_fs *rgw_fs,
    get unix attributes for object
 */
 int rgw_getattr(struct rgw_fs *rgw_fs,
-               const struct rgw_file_handle *handle, struct stat *st)
+               struct rgw_file_handle *fh, struct stat *st)
 {
   string uri;
   int rc;
 
-  rc = librgw.get_uri(handle->handle, uri);
+  rc = librgw.get_uri(fh->handle, uri);
   if (rc < 0 ) { /* invalid parent */
     return rc;
   }
@@ -269,7 +286,7 @@ int rgw_getattr(struct rgw_fs *rgw_fs,
   set unix attributes for object
 */
 int rgw_setattr(struct rgw_fs *rgw_fs,
-               const struct rgw_file_handle *handle, struct stat *st,
+               struct rgw_file_handle *fh, struct stat *st,
                uint32_t mask)
 {
   /* XXX no-op */
@@ -280,7 +297,7 @@ int rgw_setattr(struct rgw_fs *rgw_fs,
    truncate file
 */
 int rgw_truncate(struct rgw_fs *rgw_fs,
-                const struct rgw_file_handle *handle, uint64_t size)
+                struct rgw_file_handle *fh, uint64_t size)
 {
   return 0;
 }
@@ -289,8 +306,11 @@ int rgw_truncate(struct rgw_fs *rgw_fs,
    open file
 */
 int rgw_open(struct rgw_fs *rgw_fs,
-            const struct rgw_file_handle *handle, uint32_t flags)
+            struct rgw_file_handle *fh, uint32_t flags)
 {
+  RGWFileHandle* rgw_fh = get_rgwfh(fh);
+  rgw_fh->open(/* XXX */);
+
   return 0;
 }
 
@@ -298,19 +318,25 @@ int rgw_open(struct rgw_fs *rgw_fs,
    close file
 */
 int rgw_close(struct rgw_fs *rgw_fs,
-             const struct rgw_file_handle *handle, uint32_t flags)
+             struct rgw_file_handle *fh, uint32_t flags)
 {
+  RGWFileHandle* rgw_fh = get_rgwfh(fh);
+  rgw_fh->close(/* XXX */);
+
+  if (flags & RGW_CLOSE_FLAG_RELE)
+    rgw_fh->rele();
+
   return 0;
 }
 
 int rgw_readdir(struct rgw_fs *rgw_fs,
-               const struct rgw_file_handle *parent_handle, uint64_t *offset,
+               const struct rgw_file_handle *parent_fh, uint64_t *offset,
                rgw_readdir_cb rcb, void *cb_arg, bool *eof)
 {
   int rc;
   string uri;
 
-  rc = librgw.get_uri(parent_handle->handle, uri);
+  rc = librgw.get_uri(parent_fh->handle, uri);
   if (rc < 0 ) { /* invalid parent */
     return rc;
   }
@@ -347,7 +373,7 @@ int rgw_readdir(struct rgw_fs *rgw_fs,
    read data from file
 */
 int rgw_read(struct rgw_fs *rgw_fs,
-            const struct rgw_file_handle *handle, uint64_t offset,
+            struct rgw_file_handle *fh, uint64_t offset,
             size_t length, void *buffer)
 {
   return 0;
@@ -357,16 +383,18 @@ int rgw_read(struct rgw_fs *rgw_fs,
    write data to file
 */
 int rgw_write(struct rgw_fs *rgw_fs,
-             const struct rgw_file_handle *handle, uint64_t offset,
+             struct rgw_file_handle *fh, uint64_t offset,
              size_t length, void *buffer)
 {
+  RGWFileHandle* rgw_fh = get_rgwfh(fh);
+
   return 0;
 }
 
 /*
    sync written data
 */
-int rgw_fsync(struct rgw_fs *rgw_fs, const struct rgw_file_handle *handle)
+int rgw_fsync(struct rgw_fs *rgw_fs, struct rgw_file_handle *handle)
 {
   return 0;
 }
index 6eac368b2077102005100607787cb81666f8fd5c..609a6697c8f34a9ccb172c5680bb13dcf4e61a96 100644 (file)
 class RGWFileHandle
 {
   struct rgw_file_handle fh;
+  uint32_t flags;
 public:
+  static constexpr uint32_t FLAG_NONE = 0;
+  static constexpr uint32_t FLAG_OPEN = 1;
+  
   RGWFileHandle() {
     fh.fh_private = this;
   }
 
+  bool is_open() { return flags & FLAG_OPEN; }
+
+  void open() { flags |= FLAG_OPEN; }
+
+  void close() { flags &= ~FLAG_OPEN; }
+
+  void rele() {
+    /* XXX intrusive refcnt */
+    assert(! is_open());
+    delete this;
+  }
+
   struct rgw_file_handle* get_fh() { return &fh; }
 }; /* RGWFileHandle */
 
+static inline RGWFileHandle* get_rgwfh(struct rgw_file_handle* fh) {
+  return static_cast<RGWFileHandle*>(fh->fh_private);
+}
+
 class RGWLibFS
 {
   struct rgw_fs fs;
@@ -284,4 +304,60 @@ public:
 
 }; /* RGWDeleteBucketRequest */
 
+/*
+  put object
+*/
+
+class RGWPutObjRequest : public RGWLibRequest,
+                        public RGWPutObj_OS_Lib /* RGWOp */
+{
+public:
+  std::string& bucket_name;
+  std::string& obj_name;
+  buffer::list& bl; /* XXX */
+
+  RGWPutObjRequest(CephContext* _cct, RGWUserInfo *_user,
+                 std::string& _bname, std::string& _oname,
+                 buffer::list& _bl)
+    : RGWLibRequest(_cct, _user), bucket_name(_bname), obj_name(_oname),
+      bl(_bl) {
+    magic = 75;
+    op = this;
+  }
+
+  virtual bool only_bucket() { return false; }
+
+  virtual int op_init() {
+    // assign store, s, and dialect_handler
+    RGWObjectCtx* rados_ctx
+      = static_cast<RGWObjectCtx*>(get_state()->obj_ctx);
+    // framework promises to call op_init after parent init
+    assert(rados_ctx);
+    RGWOp::init(rados_ctx->store, get_state(), this);
+    op = this; // assign self as op: REQUIRED
+    return 0;
+  }
+
+  virtual int header_init() {
+
+    struct req_state* s = get_state();
+    s->info.method = "PUT";
+    s->op = OP_PUT;
+
+    /* XXX derp derp derp */
+    string uri = "/" + bucket_name + "/" + obj_name;
+    s->relative_uri = uri;
+    s->info.request_uri = uri; // XXX
+    s->info.effective_uri = uri;
+    s->info.request_params = "";
+    s->info.domain = ""; /* XXX ? */
+
+    // woo
+    s->user = user;
+
+    return 0;
+  }
+}; /* RGWPubObjRequest */
+
+
 #endif /* RGW_FILE_H */
index d56c97aa7ed89ae4991831b288d7c627e85a223e..a21e3858d9f272846a6947eaa42d7c9fa94224cf 100644 (file)
@@ -65,4 +65,15 @@ public:
   ~RGWDeleteBucket_OS_Lib() {}
 }; /* RGWCreateBucket_OS_Lib */
 
+class RGWPutObj_OS_Lib : public RGWPutObj
+{
+public:
+  RGWPutObj_OS_Lib() {}
+  ~RGWPutObj_OS_Lib() {}
+
+  virtual int verify_params();
+  virtual int get_params();
+
+}; /* RGWPutObj_OS_Lib */
+
 #endif /* RGW_OS_LIB_H */
index d741e5fdb94a9991a5b523c4f17e267c4e38cbc2..2478df2b204b11c8659ae1f2f75d669a15f6c1d0 100644 (file)
@@ -2418,7 +2418,7 @@ public:
     RWLock::WLocker wl(lock);
     entries.clear();
   }
-};
+}; /* RGWChainedCacheImpl */
 
 class RGWPutObjProcessor
 {
@@ -2449,7 +2449,7 @@ public:
                        const char *if_match = NULL, const char *if_nomatch = NULL);
 
   CephContext *ctx();
-};
+}; /* RGWPutObjProcessor */
 
 struct put_obj_aio_info {
   void *handle;
@@ -2483,7 +2483,7 @@ public:
 
   RGWPutObjProcessor_Aio(RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info) : RGWPutObjProcessor(obj_ctx, bucket_info), max_chunks(RGW_MAX_PENDING_CHUNKS), obj_len(0) {}
   virtual ~RGWPutObjProcessor_Aio();
-};
+}; /* RGWPutObjProcessor_Aio */
 
 class RGWPutObjProcessor_Atomic : public RGWPutObjProcessor_Aio
 {
@@ -2558,6 +2558,6 @@ public:
   void set_version_id(const string& vid) {
     version_id = vid;
   }
-};
+}; /* RGWPutObjProcessor_Atomic */
 
 #endif
index 46933d88702c95e11e18aa5b9ff8958fafa474b2..6f0503273a129d64669ca40c0547790f9d3cf809 100644 (file)
@@ -2415,6 +2415,22 @@ target_link_libraries(test_librgw_file_cd
   ${CMAKE_DL_LIBS}
   )
 
+# librgw_file_gp (just the rgw_file get-put bucket ops)
+add_executable(test_librgw_file_gp
+  librgw_file_gp.cc
+  $<TARGET_OBJECTS:heap_profiler_objs>
+  )
+set_target_properties(test_librgw_file_gp PROPERTIES COMPILE_FLAGS
+  ${UNITTEST_CXX_FLAGS})
+target_link_libraries(test_librgw_file_gp
+  rgw
+  librados
+  ${UNITTEST_LIBS}
+  ${EXTRALIBS}
+  ${ALLOC_LIBS}
+  ${CMAKE_DL_LIBS}
+  )
+
 if(${HAVE_LIBFUSE})
   add_executable(test_cfuse_cache_invalidate
     test_cfuse_cache_invalidate.cc
index 079272ae76357c3b90641b4f05c78286ab99a5c7..36b821005982b697a8a1baddfa018291552843f3 100644 (file)
@@ -108,8 +108,9 @@ TEST(LibRGW, LOOKUP_BUCKETS) {
 
   int ret = 0;
   for (auto& fid : fids1) {
-    struct rgw_file_handle *rgw_fh = new rgw_file_handle();
-    ret = rgw_lookup(fs, &fs->root_fh, get<0>(fid).c_str(), rgw_fh);
+    struct rgw_file_handle *rgw_fh;
+    ret = rgw_lookup(fs, &fs->root_fh, get<0>(fid).c_str(), &rgw_fh,
+                   0 /* flags */);
     ASSERT_EQ(ret, 0);
     get<2>(fid) = rgw_fh;
     ASSERT_NE(get<2>(fid), nullptr);
@@ -139,10 +140,11 @@ TEST(LibRGW, LIST_OBJECTS) {
 }
 
 TEST(LibRGW, CLEANUP) {
+  int ret = 0;
   using std::get;
   for (auto& fids : { fids1, fids2 }) {
     for (auto& fid : fids) {
-      delete get<2>(fid);
+      ret = rgw_fh_rele(fs, get<2>(fid), 0 /* flags */);
     }
   }
 }
diff --git a/src/test/librgw_file_gp.cc b/src/test/librgw_file_gp.cc
new file mode 100644 (file)
index 0000000..958d79a
--- /dev/null
@@ -0,0 +1,158 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 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.
+ *
+ */
+
+#include <stdint.h>
+#include <tuple>
+#include <iostream>
+
+#include "include/rados/librgw.h"
+#include "include/rados/rgw_file.h"
+
+#include "gtest/gtest.h"
+#include "common/ceph_argparse.h"
+#include "common/debug.h"
+#include "global/global_init.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+namespace {
+  librgw_t rgw = nullptr;
+  string uid("testuser");
+  string access_key("");
+  string secret_key("");
+  struct rgw_fs *fs = nullptr;
+
+  bool do_put = false;
+  bool do_get = false;
+  bool do_delete = false;
+
+  string bucket_name = "sorry_dave";
+  string object_name = "jocaml";
+
+  struct rgw_file_handle *fh = nullptr;
+
+  struct {
+    int argc;
+    char **argv;
+  } saved_args;
+}
+
+TEST(LibRGW, INIT) {
+  int ret = librgw_create(&rgw, nullptr, saved_args.argc, saved_args.argv);
+  ASSERT_EQ(ret, 0);
+  ASSERT_NE(rgw, nullptr);
+}
+
+TEST(LibRGW, MOUNT) {
+  int ret = rgw_mount(rgw, uid.c_str(), access_key.c_str(), secret_key.c_str(),
+                     &fs);
+  ASSERT_EQ(ret, 0);
+  ASSERT_NE(fs, nullptr);
+}
+
+TEST(LibRGW, OBJ_OPEN) {
+  int ret = rgw_lookup(fs, &fs->root_fh, bucket_name.c_str(), &fh,
+                     0 /* flags */);
+  ASSERT_EQ(ret, 0);
+  ret = rgw_open(fs, fh, 0 /* flags */);
+  ASSERT_EQ(ret, 0);
+}
+
+TEST(LibRGW, PUT_OBJECT) {
+  if (do_put) {
+    string data = "hi mom"; // fix this
+    int ret = rgw_write(fs, fh, 0, data.length(), (void*) data.c_str());
+    ASSERT_EQ(ret, 0);
+  }
+}
+
+TEST(LibRGW, GET_OBJECT) {
+  /* XXX soon */
+}
+
+TEST(LibRGW, CLEANUP) {
+  int ret = rgw_close(fs, fh, 0 /* flags */);
+  ASSERT_EQ(ret, 0);
+  ret = rgw_fh_rele(fs, fh, 0 /* flags */);
+  ASSERT_EQ(ret, 0);
+}
+
+TEST(LibRGW, UMOUNT) {
+  if (! fs)
+    return;
+
+  int ret = rgw_umount(fs);
+  ASSERT_EQ(ret, 0);
+}
+
+TEST(LibRGW, SHUTDOWN) {
+  librgw_shutdown(rgw);
+}
+
+int main(int argc, char *argv[])
+{
+  char *v{nullptr};
+  string val;
+  vector<const char*> args;
+
+  argv_to_vec(argc, const_cast<const char**>(argv), args);
+  env_to_vec(args);
+
+  v = getenv("AWS_ACCESS_KEY_ID");
+  if (v) {
+    access_key = v;
+  }
+
+  v = getenv("AWS_SECRET_ACCESS_KEY");
+  if (v) {
+    secret_key = v;
+  }
+
+  for (auto arg_iter = args.begin(); arg_iter != args.end();) {
+    if (ceph_argparse_witharg(args, arg_iter, &val, "--access",
+                             (char*) nullptr)) {
+      access_key = val;
+    } else if (ceph_argparse_witharg(args, arg_iter, &val, "--secret",
+                                    (char*) nullptr)) {
+      secret_key = val;
+    } else if (ceph_argparse_witharg(args, arg_iter, &val, "--uid",
+                                    (char*) nullptr)) {
+      uid = val;
+    } else if (ceph_argparse_witharg(args, arg_iter, &val, "--bn",
+                                    (char*) nullptr)) {
+      bucket_name = val;
+    } else if (ceph_argparse_flag(args, arg_iter, "--get",
+                                           (char*) nullptr)) {
+      do_get = true;
+    } else if (ceph_argparse_flag(args, arg_iter, "--put",
+                                           (char*) nullptr)) {
+      do_put = true;
+    } else {
+      ++arg_iter;
+    }
+  }
+
+  /* dont accidentally run as anonymous */
+  if ((access_key == "") ||
+      (secret_key == "")) {
+    std::cout << argv[0] << " no AWS credentials, exiting" << std::endl;
+    return EPERM;
+  }
+
+  saved_args.argc = argc;
+  saved_args.argv = argv;
+
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}