]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: metadata rm
authorYehuda Sadeh <yehuda@inktank.com>
Fri, 22 Mar 2013 18:01:02 +0000 (11:01 -0700)
committerYehuda Sadeh <yehuda@inktank.com>
Wed, 8 May 2013 17:57:45 +0000 (10:57 -0700)
Still needs to fix the way we remove user entries; need to take
different path, similar to put_entry())

Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
src/rgw/rgw_admin.cc
src/rgw/rgw_bucket.cc
src/rgw/rgw_common.h
src/rgw/rgw_metadata.cc
src/rgw/rgw_metadata.h
src/rgw/rgw_user.cc

index bcf16afd8f7d948fe9eaa5750da2c87f782f2c7a..4cf64051c6c0bb095b2b9fd6de9e135ea387ceeb 100644 (file)
@@ -86,6 +86,7 @@ void _usage()
   cerr << "  gc process                 manually process garbage\n";
   cerr << "  metadata get               get metadata info\n";
   cerr << "  metadata put               put metadata info\n";
+  cerr << "  metadata rm                remove metadata info\n";
   cerr << "  metadata list              list metadata info\n";
   cerr << "  mdlog show                 show metadata log\n";
   cerr << "options:\n";
@@ -191,6 +192,7 @@ enum {
   OPT_CAPS_RM,
   OPT_METADATA_GET,
   OPT_METADATA_PUT,
+  OPT_METADATA_RM,
   OPT_METADATA_LIST,
   OPT_MDLOG_SHOW,
 };
@@ -347,6 +349,8 @@ static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more)
       return OPT_METADATA_GET;
     if (strcmp(cmd, "put") == 0)
       return OPT_METADATA_PUT;
+    if (strcmp(cmd, "rm") == 0)
+      return OPT_METADATA_RM;
     if (strcmp(cmd, "list") == 0)
       return OPT_METADATA_LIST;
   } else if (strcmp(prev_cmd, "mdlog") == 0) {
@@ -510,6 +514,24 @@ static int read_decode_json(const string& infile, T& t)
   }
   return 0;
 }
+    
+static int parse_date_str(const string& date_str, utime_t& ut)
+{
+  uint64_t epoch = 0;
+
+  if (!date_str.empty()) {
+    int ret = parse_date(date_str, &epoch);
+    if (ret < 0) {
+      cerr << "ERROR: failed to parse date: " << date_str << std::endl;
+      return -EINVAL;
+    }
+  }
+
+  ut = utime_t(epoch, 0);
+
+  return 0;
+}
+
 int main(int argc, char **argv) 
 {
   vector<const char*> args;
@@ -689,6 +711,7 @@ int main(int argc, char **argv)
       switch (opt_cmd) {
         case OPT_METADATA_GET:
         case OPT_METADATA_PUT:
+        case OPT_METADATA_RM:
         case OPT_METADATA_LIST:
           metadata_key = *i;
           break;
@@ -1503,6 +1526,14 @@ next:
     }
   }
 
+  if (opt_cmd == OPT_METADATA_RM) {
+    int ret = store->meta_mgr->remove(metadata_key);
+    if (ret < 0) {
+      cerr << "ERROR: can't remove key: " << cpp_strerror(-ret) << std::endl;
+      return -ret;
+    }
+  }
+
   if (opt_cmd == OPT_METADATA_LIST) {
     void *handle;
     int max = 1000;
@@ -1541,11 +1572,19 @@ next:
     void *handle;
     list<cls_log_entry> entries;
 
+    utime_t start_time, end_time;
+
+    int ret = parse_date_str(start_date, start_time);
+    if (ret < 0)
+      return -ret;
+
+    ret = parse_date_str(end_date, end_time);
+    if (ret < 0)
+      return -ret;
+
     RGWMetadataLog *meta_log = store->meta_mgr->get_log();
 
-    utime_t from_time;
-    utime_t end_time;
-    meta_log->init_list_entries(store, from_time, end_time, &handle);
+    meta_log->init_list_entries(store, start_time, end_time, &handle);
 
     bool truncated;
 
@@ -1559,9 +1598,7 @@ next:
 
       for (list<cls_log_entry>::iterator iter = entries.begin(); iter != entries.end(); ++iter) {
         cls_log_entry& entry = *iter;
-        formatter->open_object_section("entry");
-        formatter->dump_string("name", entry.name);
-        formatter->close_section();
+        store->meta_mgr->dump_log_entry(entry, formatter);
       }
       formatter->flush(cout);
     } while (truncated);
index 9845eef8f372fe84841fcbfb7d3b708fff2d5107..5198521a2f114e0cdb766376aa4dc9adb8aeacc0 100644 (file)
@@ -26,7 +26,7 @@ using namespace std;
 void rgw_get_buckets_obj(string& user_id, string& buckets_obj_id)
 {
   buckets_obj_id = user_id;
-  buckets_obj_id += RGW_BUCKETS_OBJ_PREFIX;
+  buckets_obj_id += RGW_BUCKETS_OBJ_SUFFIX;
 }
 
 /**
index f4878f4b2916b97a910eee069701f5a336caa39e..b36055334fb3e7cfc93f1e385d718bd819dfeb6b 100644 (file)
@@ -59,7 +59,7 @@ using ceph::crypto::MD5;
 #define RGW_ATTR_MANIFEST      RGW_ATTR_PREFIX "manifest"
 #define RGW_ATTR_USER_MANIFEST  RGW_ATTR_PREFIX "user_manifest"
 
-#define RGW_BUCKETS_OBJ_PREFIX ".buckets"
+#define RGW_BUCKETS_OBJ_SUFFIX ".buckets"
 
 #define RGW_MAX_CHUNK_SIZE     (512*1024)
 #define RGW_MAX_PENDING_CHUNKS  16
index d22f5d63597177ed52a9259343a761245e395627..695372c639938203a773bb2c5b7be39ef18e7660 100644 (file)
@@ -6,6 +6,74 @@
 
 #include "rgw_rados.h"
 
+#define dout_subsys ceph_subsys_rgw
+
+enum RGWMDLogStatus {
+  MDLOG_STATUS_UNKNOWN,
+  MDLOG_STATUS_WRITING,
+  MDLOG_STATUS_REMOVING,
+  MDLOG_STATUS_COMPLETE,
+};
+
+struct LogStatusDump {
+  RGWMDLogStatus status;
+
+  LogStatusDump(RGWMDLogStatus _status) : status(_status) {}
+  void dump(Formatter *f) const {
+    string s;
+    switch (status) {
+      case MDLOG_STATUS_WRITING:
+        s = "writing";
+        break;
+      case MDLOG_STATUS_REMOVING:
+        s = "removing";
+        break;
+      case MDLOG_STATUS_COMPLETE:
+        s = "complete";
+        break;
+      default:
+        s = "unknown";
+        break;
+    }
+    encode_json("status", s, f);
+  }
+};
+
+struct RGWMetadataLogData {
+  obj_version read_version;
+  obj_version write_version;
+  RGWMDLogStatus status;
+  
+  RGWMetadataLogData() : status(MDLOG_STATUS_UNKNOWN) {}
+
+  void encode(bufferlist& bl) const {
+    ENCODE_START(1, 1, bl);
+    ::encode(read_version, bl);
+    ::encode(write_version, bl);
+    uint32_t s = (uint32_t)status;
+    ::encode(s, bl);
+    ENCODE_FINISH(bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+     DECODE_START(1, bl);
+     ::decode(read_version, bl);
+     ::decode(write_version, bl);
+     uint32_t s;
+     ::decode(s, bl);
+     status = (RGWMDLogStatus)s;
+     DECODE_FINISH(bl);
+  }
+
+  void dump(Formatter *f) const {
+    encode_json("read_version", read_version, f);
+    encode_json("write_version", write_version, f);
+    encode_json("status", LogStatusDump(status), f);
+  };
+};
+WRITE_CLASS_ENCODER(RGWMetadataLogData);
+
+
 int RGWMetadataLog::add_entry(RGWRados *store, string& section, string& key, bufferlist& bl) {
   string oid;
 
@@ -49,7 +117,7 @@ int RGWMetadataLog::list_entries(void *handle,
     bool is_truncated;
     int ret = store->time_log_list(ctx->cur_oid, ctx->from_time, ctx->end_time,
                                  max_entries - entries.size(), ents, ctx->marker, &is_truncated);
-    if (ret = -ENOENT) {
+    if (ret == -ENOENT) {
       is_truncated = false;
       ret = 0;
     }
@@ -95,8 +163,9 @@ public:
 
   virtual int get(RGWRados *store, string& entry, RGWMetadataObject **obj) { return -ENOTSUP; }
   virtual int put(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker, JSONObj *obj) { return -ENOTSUP; }
-  virtual int put_obj(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
-                      RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs) { return -ENOTSUP; }
+  virtual int put_entry(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
+                        RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs) { return -ENOTSUP; }
+  virtual int remove(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker) { return -ENOTSUP; }
 
   virtual int list_keys_init(RGWRados *store, void **phandle) {
     iter_data *data = new iter_data;
@@ -126,7 +195,7 @@ public:
 
 static RGWMetadataTopHandler md_top_handler;
 
-RGWMetadataManager::RGWMetadataManager(CephContext *_cct, RGWRados *_store) : store(_store)
+RGWMetadataManager::RGWMetadataManager(CephContext *_cct, RGWRados *_store) : cct(_cct), store(_store)
 {
   md_log = new RGWMetadataLog(_cct, _store);
 }
@@ -236,7 +305,6 @@ int RGWMetadataManager::put(string& metadata_key, bufferlist& bl)
     return -EINVAL;
   }
 
-  string meadata_key;
   RGWObjVersionTracker objv_tracker;
 
   obj_version *objv = &objv_tracker.write_version;
@@ -253,6 +321,59 @@ int RGWMetadataManager::put(string& metadata_key, bufferlist& bl)
   return handler->put(store, entry, objv_tracker, jo);
 }
 
+int RGWMetadataManager::remove(string& metadata_key)
+{
+  RGWMetadataHandler *handler;
+  string entry;
+
+  int ret = find_handler(metadata_key, &handler, entry);
+  if (ret < 0)
+    return ret;
+
+  RGWMetadataObject *obj;
+
+  ret = handler->get(store, entry, &obj);
+  if (ret < 0) {
+    return ret;
+  }
+
+  RGWObjVersionTracker objv_tracker;
+
+  objv_tracker.read_version = obj->get_version();
+
+
+  RGWMetadataLogData log_data;
+  bufferlist logbl;
+
+  log_data.read_version = objv_tracker.read_version;
+  log_data.write_version = objv_tracker.write_version;
+
+  log_data.status = MDLOG_STATUS_REMOVING;
+
+  ::encode(log_data, logbl);
+
+  string section, key;
+  parse_metadata_key(entry, section, key);
+
+  ret = md_log->add_entry(store, section, key, logbl);
+  if (ret < 0)
+    return ret;
+
+  ret = handler->remove(store, entry, objv_tracker);
+  if (ret < 0) {
+    return ret;
+  }
+
+  logbl.clear();
+  log_data.status = MDLOG_STATUS_COMPLETE;
+
+  ret = md_log->add_entry(store, section, key, logbl);
+  if (ret < 0)
+    return ret;
+
+  return 0;
+}
+
 
 struct list_keys_handle {
   void *handle;
@@ -305,6 +426,25 @@ void RGWMetadataManager::list_keys_complete(void *handle)
   delete h;
 }
 
+void RGWMetadataManager::dump_log_entry(cls_log_entry& entry, Formatter *f)
+{
+  f->open_object_section("entry");
+  f->dump_string("section", entry.section);
+  f->dump_string("name", entry.name);
+  entry.timestamp.gmtime(f->dump_stream("timestamp"));
+
+  try {
+    RGWMetadataLogData log_data;
+    bufferlist::iterator iter = entry.data.begin();
+    ::decode(log_data, iter);
+
+    encode_json("data", log_data, f);
+  } catch (buffer::error& err) {
+    lderr(cct) << "failed to decode log entry: " << entry.section << ":" << entry.name<< " ts=" << entry.timestamp << dendl;
+  }
+  f->close_section();
+}
+
 void RGWMetadataManager::get_sections(list<string>& sections)
 {
   for (map<string, RGWMetadataHandler *>::iterator iter = handlers.begin(); iter != handlers.end(); ++iter) {
@@ -312,20 +452,42 @@ void RGWMetadataManager::get_sections(list<string>& sections)
   }
 }
 
-
-int RGWMetadataManager::put_obj(RGWMetadataHandler *handler, string& key, bufferlist& bl, bool exclusive,
-                                RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs)
+int RGWMetadataManager::put_entry(RGWMetadataHandler *handler, string& key, bufferlist& bl, bool exclusive,
+                                  RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs)
 {
   bufferlist logbl;
   string section = handler->get_type();
+
+  /* if write version has not been set, and there's a read version, set it so that we can
+   * log it
+   */
+  if (objv_tracker && objv_tracker->read_version.ver &&
+      !objv_tracker->write_version.ver) {
+    objv_tracker->write_version = objv_tracker->read_version;
+    objv_tracker->write_version.ver++;
+  }
+
+  RGWMetadataLogData log_data;
+  log_data.read_version = objv_tracker->read_version;
+  log_data.write_version = objv_tracker->write_version;
+
+  log_data.status = MDLOG_STATUS_WRITING;
+
+  ::encode(log_data, logbl);
+
   int ret = md_log->add_entry(store, section, key, logbl);
   if (ret < 0)
     return ret;
 
-  ret = handler->put_obj(store, key, bl, exclusive, objv_tracker, pattrs);
+  ret = handler->put_entry(store, key, bl, exclusive, objv_tracker, pattrs);
   if (ret < 0)
     return ret;
 
+  log_data.status = MDLOG_STATUS_COMPLETE;
+
+  logbl.clear();
+  ::encode(log_data, logbl);
+
   ret = md_log->add_entry(store, section, key, logbl);
   if (ret < 0)
     return ret;
index bee940779f5269ed8ec154a79e9fb3d27e18ae07..686e41ca116c79a9b7ba82766620f284d1f645b6 100644 (file)
@@ -33,15 +33,15 @@ class RGWMetadataHandler {
   friend class RGWMetadataManager;
 
 protected:
-  virtual int put_obj(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
-                      RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL) = 0;
+  virtual int put_entry(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
+                        RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL) = 0;
 public:
   virtual ~RGWMetadataHandler() {}
   virtual string get_type() = 0;
 
   virtual int get(RGWRados *store, string& entry, RGWMetadataObject **obj) = 0;
   virtual int put(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker, JSONObj *obj) = 0;
-
+  virtual int remove(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker) = 0;
 
   virtual int list_keys_init(RGWRados *store, void **phandle) = 0;
   virtual int list_keys_next(void *handle, int max, list<string>& keys, bool *truncated) = 0;
@@ -92,6 +92,7 @@ public:
 
 class RGWMetadataManager {
   map<string, RGWMetadataHandler *> handlers;
+  CephContext *cct;
   RGWRados *store;
   RGWMetadataLog *md_log;
 
@@ -107,15 +108,18 @@ public:
 
   RGWMetadataHandler *get_handler(const char *type);
 
-  int put_obj(RGWMetadataHandler *handler, string& key, bufferlist& bl, bool exclusive,
-              RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL);
+  int put_entry(RGWMetadataHandler *handler, string& key, bufferlist& bl, bool exclusive,
+                RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs = NULL);
   int get(string& metadata_key, Formatter *f);
   int put(string& metadata_key, bufferlist& bl);
+  int remove(string& metadata_key);
 
   int list_keys_init(string& section, void **phandle);
   int list_keys_next(void *handle, int max, list<string>& keys, bool *truncated);
   void list_keys_complete(void *handle);
 
+  void dump_log_entry(cls_log_entry& entry, Formatter *f);
+
   void get_sections(list<string>& sections);
 
   RGWMetadataLog *get_log() { return md_log; }
index a6b72923f556e0b74d8b2e3488110cebc8034694..85798189d980535594a2d070b8fbcd6660bc8db3 100644 (file)
@@ -91,7 +91,7 @@ int rgw_store_user_info(RGWRados *store, RGWUserInfo& info, RGWUserInfo *old_inf
   ::encode(ui, data_bl);
   ::encode(info, data_bl);
 
-  ret = store->meta_mgr->put_obj(user_meta_handler, info.user_id, data_bl, exclusive, objv_tracker);
+  ret = store->meta_mgr->put_entry(user_meta_handler, info.user_id, data_bl, exclusive, objv_tracker);
   if (ret < 0)
     return ret;
 
@@ -1542,7 +1542,7 @@ int RGWUser::update(RGWUserAdminOpState& op_state, std::string *err_msg)
   }
 
   if (is_populated()) {
-    ret = rgw_store_user_info(store, user_info, &old_info, NULL, false);
+    ret = rgw_store_user_info(store, user_info, &old_info, &op_state.objv, false);
     if (ret < 0) {
       set_err_msg(err_msg, "unable to store user info");
       return ret;
@@ -2276,8 +2276,20 @@ public:
     RGWListRawObjsCtx ctx;
   };
 
-  int put_obj(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
-              RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs) {
+  int remove(RGWRados *store, string& entry, RGWObjVersionTracker& objv_tracker) {
+#warning FIXME: use objv_tracker
+
+    RGWUserInfo info;
+    RGWObjVersionTracker ot;
+    int ret = rgw_get_user_info_by_uid(store, entry, info, &ot);
+    if (ret < 0)
+      return ret;
+
+    return rgw_delete_user(store, info);
+  }
+
+  int put_entry(RGWRados *store, string& key, bufferlist& bl, bool exclusive,
+                RGWObjVersionTracker *objv_tracker, map<string, bufferlist> *pattrs) {
     return rgw_put_system_obj(store, store->zone.user_uid_pool, key,
                               bl.c_str(), bl.length(), exclusive,
                               objv_tracker, pattrs);